Java 在不安装 SMTP 服务器的情况下测试 Greenmail

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9661907/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 05:46:28  来源:igfitidea点击:

Testing Greenmail without installing a SMTP server

javaspringemailgreenmail

提问by Hoàng Long

I'm trying to use Greenmail to unit test email functions on my localhost. The problem is that I don't have a SMTP server installed already, and feels it over-killing to install one. My expectation is that there should be a free library that allow me keep my sending mail code the same, but instead of truly sending email to a SMTP server, send it to my local machine so that I can retrieve them (for the sake of unit testing).

我正在尝试使用 Greenmail 在我的本地主机上对电子邮件功能进行单元测试。问题是我还没有安装 SMTP 服务器,我觉得安装一个太麻烦了。我的期望是应该有一个免费的库,允许我保持我的发送邮件代码相同,但不是真正将电子邮件发送到 SMTP 服务器,而是将其发送到我的本地机器,以便我可以检索它们(为了单位测试)。

I once used Greenmail when developing with Grails,and the experience is great. But I can't find something similar for Spring Framework. In Greenmailpage, it says that there's a mocking SMTP server bundled with JBoss. But I don't want to run JBoss, since currently my web application is running on Tomcat.

我曾经在用Grails开发的时候用过Greenmail,体验很棒。但是我找不到 Spring Framework 类似的东西。在Greenmail页面中,它说 JBoss 捆绑了一个模拟SMTP 服务器。但我不想运行 JBoss,因为目前我的 Web 应用程序正在 Tomcat 上运行。

Is there any similar service for Tomcat already? Or are there any better way to send test email to localhost, where I can retrieve the emails sent?

Tomcat 已经有类似的服务了吗?或者有没有更好的方法将测试电子邮件发送到本地主机,在那里我可以检索发送的电子邮件?

UPDATE:

更新

I tried using Ralph's method, but it still yield the same exception:

我尝试使用 Ralph 的方法,但它仍然产生相同的异常:

[SimpleAsyncTaskExecutor-1] 2012-03-13 10:19:39,475 - ERROR: com.test.my.service.emailing.impl.EmailServiceImpl - Mail server connection failed; nested exception is javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 3025;
  nested exception is:
    java.net.ConnectException: Connection refused: connect. Failed messages: javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 3025;
  nested exception is:
    java.net.ConnectException: Connection refused: connect
org.springframework.mail.MailSendException: Mail server connection failed; nested exception is javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 3025;
  nested exception is:
    java.net.ConnectException: Connection refused: connect. Failed messages: javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 3025;
  nested exception is:
    java.net.ConnectException: Connection refused: connect; message exception details (1) are:
Failed message 1:
javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 3025;
  nested exception is:
    java.net.ConnectException: Connection refused: connect
    at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1391)
    at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:412)
    at javax.mail.Service.connect(Service.java:288)
    at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:389)
    at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:340)
    at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:336)
    at com.test.my.service.emailing.impl.EmailServiceImpl.test(EmailServiceImpl.java:388)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.interceptor.AsyncExecutionInterceptor.call(AsyncExecutionInterceptor.java:80)
    at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.net.ConnectException: Connection refused: connect
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(Unknown Source)
    at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
    at java.net.PlainSocketImpl.connect(Unknown Source)
    at java.net.SocksSocketImpl.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:233)
    at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:189)
    at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1359)
    ... 19 more

采纳答案by Ralph

You can use Greenmailwith any Java Program, no matter if it is using Spring or not. You do not need any Spring specific stuff for it.

您可以将Greenmail与任何 Java 程序一起使用,无论它是否使用 Spring。您不需要任何特定于 Spring 的东西。

It run some kind of in process mail server.

它运行某种进程中的邮件服务器。

import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.GreenMailUtil;
import com.icegreen.greenmail.util.ServerSetupTest; ...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("ApplicationContext-Greenmail.xml")
public class EmailServiceIntegrationTest {

    /** Class under test */
    @Resource
    private EmailService emailService;

    private GreenMail greenMail;

    @Before
    public void startMailServer() {
        greenMail = new GreenMail(ServerSetupTest.SMTP);
        greenMail.start();
    }

    @After
    public void stopMailServer() {
        greenMail.stop();
    }

    @Test
    public void testPledgeReminder()
                throws InterruptedException, MessagingException {

        String mailText = "Hallo World";
        String mailSubject = "Hallo";
        String mailTo = "[email protected]";

        /** when: sending a mail */
        emailService.send(mailSubject, mailTo, mailText);

        assertTrue(greenMail.waitForIncomingEmail(5000, 1));
        Message[] messages = greenMail.getReceivedMessages();
        assertEquals(1, messages.length);
        assertEquals(mailText, messages[0].getSubject());       
        String body = GreenMailUtil.getBody(messages[0]).replaceAll("=\r?\n", "");
        assertEquals(mailText, body);       
    }

}

important: use port 3025

重要:使用端口 3025

<bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <property name="javaMailProperties">
        <util:properties>
            <prop key="mail.debug">false</prop>
            <prop key="mail.transport.protocol">smtp</prop>
            <prop key="mail.smtp.port">3025</prop>
            <prop key="mail.smtp.auth">true</prop>
            <prop key="mail.smtp.user">[email protected]</prop>
            <prop key="mail.smtp.host">localhost</prop>
            <prop key="mail.smtp.from">[email protected]</prop>
        </util:properties>
    </property>
    <property name="username" value="test"/>
    <property name="password" value="xxx"/>
    <property name="defaultEncoding" value="utf8" />
</bean>

Then this configuration will configure a Spring JavaMailSender to send its mails to the GreenMail-Server started and finished by the test code.

然后这个配置将配置一个 Spring JavaMailSender 将它的邮件发送到由测试代码启动和完成的 GreenMail-Server。

回答by ndeverge

It seems that someone once proposed such integration : http://sourceforge.net/mailarchive/forum.php?thread_name=45DEB9E3.6090608%40consol.de&forum_name=greenmail-developers

似乎有人曾经提出过这样的整合:http: //sourceforge.net/mailarchive/forum.php?thread_name=45DEB9E3.6090608%40consol.de&forum_name=greenmail-developers

Don't know if it's still working...

不知道还有没有用。。。

回答by TrueDub

Edit (2017 Nov):

编辑(2017 年 11 月):

Dumbster link is dead, there is a fork of it on github https://github.com/kirviq/dumbster

Dumbster 链接已死,github 上有一个 fork https://github.com/kirviq/dumbster

---- Original message ----

- - 原始信息 - -

Have a look at Dumbster - I use it for all my unit testing, as it allows me to assert against the actual emails sent out.

看看 Dumbster - 我将它用于我所有的单元测试,因为它允许我对发送的实际电子邮件进行断言。

http://quintanasoft.com/dumbster/

http://quintanasoft.com/dumbster/

回答by leeor

Doing something like this in a springtest works fine for me:

spring测试中做这样的事情对我来说很好:

ServerSetupTest.setPortOffset(<SOME_CUSTOM_PORT>);
testEmailServer = new GreenMail();
testEmailServer.start();

The main idea behind the ServerSetupTestclass is to create a ServerSetupwith a user-defined port offset for testing. See the docsfor more details.

ServerSetupTest该类背后的主要思想是创建一个ServerSetup具有用户定义的端口偏移量以进行测试。有关更多详细信息,请参阅文档

回答by user4457779

Try to set GreenMail server's port manually like this:

尝试像这样手动设置 GreenMail 服务器的端口:

 @Before
public void startMailServer()
    throws Exception
{
    ServerSetup setup = new ServerSetup(3025,"localhost","smtp");
    greenMail = new GreenMail(setup);
    greenMail.start();
}

and then set your email sender's port the same as above, pay attention to protocol/host/port:

然后将您的电子邮件发件人的端口设置为与上述相同,注意协议/主机/端口:

email.protocol=smtp
email.host=localhost
email.port=3025
[email protected]
[email protected]
email.auth=true
[email protected]

with bean configuration:

使用bean配置:

<bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <property name="protocol" value="${email.protocol}" />
    <property name="host" value="${email.host}" />
    <property name="port" value="${email.port}" />
    <property name="username" value="${email.username}" />
    <property name="password" value="${email.password}" />
    <property name="javaMailProperties">
        <props>
            <prop key="mail.${email.protocol}.auth">${email.auth}</prop>
        </props>
    </property>
</bean>