Sending mails form grails does not work - email

I have a problem with sending mails from grails. Add an exception to port 587, but nothing helped. Still an error occur:
Connection refused: connect. Stacktrace follows:
java.lang.reflect.InvocationTargetException: null
at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:211)
at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:188)
at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.mail.MailSendException: Mail server connection failed; nested exception is com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeout -1;
nested exception is:
java.net.ConnectException: Connection refused: connect. Failed messages: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeout -1;
nested exception is:
java.net.ConnectException: Connection refused: connect
at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:432)
at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:345)
at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:340)
at grails.plugins.mail.MailMessageBuilder.sendMessage(MailMessageBuilder.groovy:131)
at grails.plugins.mail.MailService.sendMail(MailService.groovy:55)
at grails.plugins.mail.MailService.sendMail(MailService.groovy:59)
at grailsproject.UserController.save(UserController.groovy:31)
... 14 common frames omitted
Caused by: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeout -1
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2118)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:712)
at javax.mail.Service.connect(Service.java:366)
at org.springframework.mail.javamail.JavaMailSenderImpl.connectTransport(JavaMailSenderImpl.java:501)
at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:421)
... 20 common frames omitted
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:331)
at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:238)
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2084)
... 24 common frames omitted
application.yml
mail:
host: "smtp.gmail.com"
port: 465
username: "***#gmail.com"
password: "***"
props:
mail.smtp.auth: "true"
mail.smtp.socketFactory.port: "465"
mail.smtp.socketFactory.class: "javax.net.ssl.SSLSocketFactory"
mail.smtp.socketFactory.fallback: "true"
build.gradle
runtime "org.grails.plugins:mail:2.0.0.RC4"
I have tried also with:
runtime "org.grails.plugins:mail:2.0.0"
runtime "org.grails.plugins:mail:2.0.0.RC6"
and also does not work.
UserController.groovy
package grailsproject
class UserController {
def mailService
def form() {
}
def save() {
def user = new Userr(params)
user.validate()
if(user.hasErrors())
{
user.errors.allErrors.each {
println it
}
render (view:"/registrationForm/registrationForm", model: [user: user]);
}else
{
user.save(flush: true)
render(view: "user", model: [user: user]);
}
mailService.sendMail{
to "***#gmail.com"
from "***#gmail.com"
subject "This is a test mail"
body "Hello, This is a test mail, how are you?"
}
}
}
I do not have idea, what else should I check...
I am also wondering why it try to connect localhost when I gave there gmail host?

Your application.yml should be
grails:
mail:
host: "smtp.gmail.com"
port: 465
username: "your_mail#gmail.com"
password: "Your_password"
props:
mail.smtp.auth: "true"
mail.smtp.socketFactory.port: "465"
mail.smtp.socketFactory.class: "javax.net.ssl.SSLSocketFactory"
mail.smtp.socketFactory.fallback: "false"
build.gradle wiil be
compile "org.grails.plugins:mail:2.0.0.RC6"
UserController.groovy should be
package grailsproject
class UserController {
def index() { }
def send() {
def multipartFile = request.getFile('attachment')
sendMail {
multipart true
to params.address
subject params.subject
html params.body
if(multipartFile && !multipartFile.empty) {
File tmpFile = new File(System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") + multipartFile.getOriginalFilename());
multipartFile.transferTo(tmpFile);
attach tmpFile
}
}
flash.message = "Email Sent Successfully"
redirect action:"index"
}
}

Related

ActiveMQ in Eclipse to listen to remote broker

My goal is to listen to a broker on a port on a specific IP address with a given topic to receive JMS messages from there with ActiveMQ in Eclipse IDE.
Here is my code:
public static void main(String[] args) throws URISyntaxException, Exception {
Connection Connection = null;
try {
// Producer
ConnectionFactory ConnectionFactory = new ActiveMQConnectionFactory("tcp://1.2.3.4:5678");
Connection = ConnectionFactory.createConnection();
Connection.start();
Session session = Connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic("MyTopic");
// Consumer1 subscribes to customerTopic
MessageConsumer consumer1 = session.createConsumer(topic);
consumer1.setMessageListener(new MessageConsumeListener("MyTopic"));
System.out.print("connected");
Thread.sleep(3000);
/* session.close(); */
} finally {
if (Connection != null) {
Connection.close();
}
}
}
This is the error:
Exception in thread "main" javax.jms.JMSException: Could not connect to broker URL: tcp://1.2.3.4.5678 Reason: java.net.ConnectException: Connection refused (Connection refused)
at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:36)
at org.apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.java:360)
at org.apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.java:305)
at org.apache.activemq.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:245)
at My.Project.subscribelistener.main(subscribelistener.java:29)
And also this:
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.base/java.net.PlainSocketImpl.socketConnect(Native Method)
at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:399)
at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:242)
at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:224)
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.base/java.net.Socket.connect(Socket.java:609)
at org.apache.activemq.transport.tcp.TcpTransport.connect(TcpTransport.java:501)
at org.apache.activemq.transport.tcp.TcpTransport.doStart(TcpTransport.java:464)
at org.apache.activemq.util.ServiceSupport.start(ServiceSupport.java:55)
at org.apache.activemq.transport.AbstractInactivityMonitor.start(AbstractInactivityMonitor.java:168)
at org.apache.activemq.transport.InactivityMonitor.start(InactivityMonitor.java:50)
at org.apache.activemq.transport.TransportFilter.start(TransportFilter.java:58)
at org.apache.activemq.transport.WireFormatNegotiator.start(WireFormatNegotiator.java:72)
at org.apache.activemq.transport.TransportFilter.start(TransportFilter.java:58)
at org.apache.activemq.transport.TransportFilter.start(TransportFilter.java:58)
at org.apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.java:340)
... 3 more
I can also ping the IP address and with telnet I can connect to the port.
How can I connect to a remote broker?

How to catch SOAP request message in CXF with WSS4JOutInterceptor when connection fails

I can catch SOAP request message according to
this SO answer.
However if the server is unavailable I get the following exception from SAAJOutInterceptor (added by WSS4JOutInterceptor) and LoggingCallback is not invoked hence message is not caugth:
org.apache.cxf.binding.soap.SoapFault: Connection refused: connect
at org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor$SAAJOutEndingInterceptor.handleMessage(SAAJOutInterceptor.java:221)
at org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor$SAAJOutEndingInterceptor.handleMessage(SAAJOutInterceptor.java:174)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:531)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:440)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:355)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:313)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:140)
...
Caused by: com.ctc.wstx.exc.WstxIOException: Connection refused: connect
at com.ctc.wstx.sw.BaseStreamWriter.flush(BaseStreamWriter.java:262)
at org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor$SAAJOutEndingInterceptor.handleMessage(SAAJOutInterceptor.java:215)
...
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at sun.net.NetworkClient.doConnect(NetworkClient.java:175)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:463)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:558)
at sun.net.www.http.HttpClient.<init>(HttpClient.java:242)
at sun.net.www.http.HttpClient.New(HttpClient.java:339)
at sun.net.www.http.HttpClient.New(HttpClient.java:357)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1220)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1199)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1050)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:984)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1334)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1309)
at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.setupWrappedStream(URLConnectionHTTPConduit.java:274)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleHeadersTrustCaching(HTTPConduit.java:1345)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.onFirstWrite(HTTPConduit.java:1306)
at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.onFirstWrite(URLConnectionHTTPConduit.java:307)
at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:47)
at org.apache.cxf.io.AbstractThresholdOutputStream.unBuffer(AbstractThresholdOutputStream.java:89)
at org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:63)
at org.apache.cxf.io.CacheAndWriteOutputStream.write(CacheAndWriteOutputStream.java:80)
at org.apache.cxf.io.CacheAndWriteOutputStream.write(CacheAndWriteOutputStream.java:80)
at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:51)
at com.ctc.wstx.io.UTF8Writer.flush(UTF8Writer.java:100)
at com.ctc.wstx.sw.BufferingXmlWriter.flush(BufferingXmlWriter.java:242)
at com.ctc.wstx.sw.BaseStreamWriter.flush(BaseStreamWriter.java:260)
...
I need to save request SOAP message with all the security stuff added by WSS4JOutInterceptor (certificate, signature ...) regardless of whether the message was successfully send or whether the server is even up.
The thing is that you must first write to the output stream where you catch the message and write to network connection only in onClose callback:
class RequestInterceptor extends AbstractPhaseInterceptor<Message> {
OutputStream outputStream
OutputStream originalOutputStream
public RequestInterceptor() {
super(Phase.PRE_STREAM);
}
#Override
public void handleMessage(Message message) throws Fault {
originalOutputStream = message.getContent(OutputStream.class)
CacheAndWriteOutputStream newOutputStream = new CacheAndWriteOutputStream(outputStream)
message.setContent(OutputStream.class, newOutputStream)
newOutputStream.registerCallback(new CachedOutputStreamCallback() {
void onFlush(CachedOutputStream cos) {
}
void onClose(CachedOutputStream cos) {
cos.writeCacheTo(originalOutputStream)
originalOutputStream.close()
}
})
}
}

Mail server connection failed while configuring gmail at server but works perfectly on local machine

Error:
org.springframework.mail.MailSendException: Mail server connection failed; nested exception is javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 465; nested exception is: java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext). Failed messages: javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 465; nested exception is: java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext); message exception details (1) are:Failed message 1:javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 465; nested exception is: java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext) at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1986) at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:656) at javax.mail.Service.connect(Service.java:345) at grails.plugin.mail.MailMessageBuilder.sendMessage(MailMessageBuilder.groovy:131) at grails.plugin.mail.MailService.sendMail(MailService.groovy:55) at grails.plugin.mail.MailService.sendMail(MailService.groovy:59) at grails.plugin.springsecurity.ui.strategy.MailPluginMailStrategy.sendMail(MailPluginMailStrategy.groovy:50) at grails.plugin.springsecurity.ui.strategy.MailPluginMailStrategy.sendVerifyRegistrationMail(MailPluginMailStrategy.groovy:34) at grails.plugin.springsecurity.ui.RegisterController.sendVerifyRegistrationMail(RegisterController.groovy:79) at register
config.groovy
mail {
host = "smtp.gmail.com"
port = 465
username = "*******#gmail.com"
password = "********"
props = ["mail.smtp.auth":"true",
"mail.smtp.socketFactory.port":"465",
"mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
"mail.smtp.socketFactory.fallback":"false"]
}

Play Mailer plugin with Play 2.5

I am struggling with play mailer plugin. I found many references to configure play-mailer plugin to send email using gmail, but none worked.
Here are the details -
Play 2.5
Scala 2.11
mailer plugin - "com.typesafe.play" %% "play-mailer" % "5.0.0"
And here is my code:
application.conf:
play.mailer {
host="smtp.gmail.com"
port=587
ssl=no
tls=yes
user="pariXXXXXX#gmail.com"
password="XXXXXX"
debug=no
timeout=60
connectiontimeout=60
mock=false
}
Controller:
class HomeController #Inject() (
val messagesApi: MessagesApi,
val mailer:MailerClient)
extends Controller with I18nSupport {
def index = Action {
val bodyHtml = Some(views.html.mails.welcome("Pari").toString)
val email = Email(subject = "subject", from = "pari.XXXXX#gmail.com", to = List("pari.XXXXX#gmail.com"), bodyHtml = bodyHtml, bodyText = Some("Hello"), replyTo = None)
mailer.send(email)
Ok("Did you receive my email?")
}
}
Error:
Execution exception[[EmailException: Sending the email to the following server failed : smtp.gmail.com:587]]
at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:280)
at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:206)
at play.api.GlobalSettings$class.onError(GlobalSettings.scala:160)
at play.api.DefaultGlobal$.onError(GlobalSettings.scala:188)
at play.api.http.GlobalSettingsHttpErrorHandler.onServerError(HttpErrorHandler.scala:98)
at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:100)
at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:99)
at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:344)
at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:343)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
Caused by: org.apache.commons.mail.EmailException: Sending the email to the following server failed : smtp.gmail.com:587
at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1421)
at org.apache.commons.mail.Email.send(Email.java:1448)
at play.api.libs.mailer.SMTPMailer$$anon$2.send(MailerPlugin.scala:100)
at play.api.libs.mailer.CommonsMailer.send(MailerPlugin.scala:130)
at play.api.libs.mailer.SMTPMailer.send(MailerPlugin.scala:110)
at play.api.libs.mailer.SMTPDynamicMailer.send(MailerPlugin.scala:117)
at controllers.HomeController$$anonfun$index$1.apply(HomeController.scala:82)
at controllers.HomeController$$anonfun$index$1.apply(HomeController.scala:79)
at play.api.mvc.ActionBuilder$$anonfun$apply$14.apply(Action.scala:403)
at play.api.mvc.ActionBuilder$$anonfun$apply$14.apply(Action.scala:403)
Caused by: javax.mail.MessagingException: Exception reading response
at com.sun.mail.smtp.SMTPTransport.readServerResponse(SMTPTransport.java:2202)
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1939)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:654)
at javax.mail.Service.connect(Service.java:317)
at javax.mail.Service.connect(Service.java:176)
at javax.mail.Service.connect(Service.java:125)
at javax.mail.Transport.send0(Transport.java:194)
at javax.mail.Transport.send(Transport.java:124)
at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1411)
at org.apache.commons.mail.Email.send(Email.java:1448)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at com.sun.mail.util.TraceInputStream.read(TraceInputStream.java:124)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at com.sun.mail.util.LineInputStream.readLine(LineInputStream.java:89)
at com.sun.mail.smtp.SMTPTransport.readServerResponse(SMTPTransport.java:2182)
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1939)
Any thoughts?
P.S. I have enabled less secure access for gmail account as well.
You simply need to provide play mailer configuration in your application.conf as below
play.mailer.host= "smtp.gmail.com"
play.mailer.port= "46"
play.mailer.ssl= true
play.mailer.user="pari.XXXX#gmail.com"
play.mailer.password="XXXXXXXXXX"
I have replaced play.mailer block with smtp.mock. After this change I am getting email sent by application.
smtp.mock=false
smtp {
host="smtp.gmail.com" #example:
port="465" #example: 465
ssl=true
user="pari.XXXX#gmail.com"
password="XXXXXXXXXX"
from="XXXXXXX"
}
However, I am getting warning -
smtp is deprecated, use play.mailer instead
Anybody has any idea, how to configure mailer configs.
Thanks
Pari

Having trouble mocking an email server using JUnit

I'm trying to mock sending an email (for the purposes of JUnit, v4.8.1, testing) and decided to use Dumbster, which I found through SO. I'm using version 1.6. I have this in my JUnit test …
SimpleSmtpServer server = SimpleSmtpServer.start();
boolean ret = m_emailSvc.sendEmail("me#me.com",
"you#you.com",
"localhost",
"Test",
"Test Body");
Assert.assertTrue(ret);
server.stop();
and I send an email this way …
public boolean sendEmail(final String toEmail,
final String fromEmail,
final String smtpHost,
final String subject,
final String body)
{
boolean ret = true;
// Get system properties
Properties properties = System.getProperties();
// Setup mail server
properties.setProperty("mail.smtp.host", smtpHost);
// Get the default Session object.
Session session = Session.getDefaultInstance(properties);
try{
// Create a default MimeMessage object.
MimeMessage message = new MimeMessage(session);
// Set From: header field of the header.
message.setFrom(new InternetAddress(fromEmail));
// Set To: header field of the header.
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(toEmail));
// Set Subject: header field
message.setSubject(subject);
// Now set the actual message
message.setText(body);
// Send message
Transport.send(message);
}catch (MessagingException mex) {
ret = false;
LOG.error(mex.getMessage(), mex);
} // try
return ret;
} // sendEmail
This fails with the exception below. Does anyone know what I'm doing wrong or is there an easier way to mock sending an email in a JUnit test?
java.net.BindException: Permission denied
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.PlainSocketImpl.socketBind(PlainSocketImpl.java:521)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:414)
at java.net.ServerSocket.bind(ServerSocket.java:326)
at java.net.ServerSocket.<init>(ServerSocket.java:192)
at java.net.ServerSocket.<init>(ServerSocket.java:104)
at com.dumbster.smtp.SimpleSmtpServer.run(Unknown Source)
at java.lang.Thread.run(Thread.java:680)
[ERROR]: org.mainco.subco.email.service.EmailServiceImpl - Could not connect to SMTP host: localhost, port: 25
javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 25;
nested exception is:
java.net.ConnectException: Connection refused
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1934)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:638)
at javax.mail.Service.connect(Service.java:295)
at javax.mail.Service.connect(Service.java:176)
at javax.mail.Service.connect(Service.java:125)
at javax.mail.Transport.send0(Transport.java:194)
at javax.mail.Transport.send(Transport.java:124)
at org.mainco.subco.email.service.EmailServiceImpl.sendEmail(EmailServiceImpl.java:62)
at org.mainco.subco.email.service.EmailServiceTest.testSendEmail(EmailServiceTest.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:382)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:241)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:228)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:384)
at java.net.Socket.connect(Socket.java:527)
at java.net.Socket.connect(Socket.java:476)
at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:288)
at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:231)
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1900)
I decided to mock the static call from the Transport class instead, using PowerMock (v.1.5.1).
#RunWith(PowerMockRunner.class)
public class EmailServiceTest
{
#Autowired
private EmailService m_emailSvc = new EmailServiceImpl();
#Test
#PrepareForTest( Transport.class )
public final void testSendEmail()
{
suppress(methodsDeclaredIn(Transport.class));
boolean ret = m_emailSvc.sendEmail("me#me.com",
"you#you.com",
"localhost",
"Test",
"Test Body");
Assert.assertTrue(ret);
} // testSendEmail
What about wrapping the call to Transport is a mockable object? Inject the mock and verify the call.
What I mean is something like this...
class MyTransport{
public void send(MimeMessage message){
Transport.send(message);
}
}
Then inject an instance of this class into your class above. In your production env you have the same code. However, when doing testing you could pass in a Mock for MyTransport and thereby verify the call to send without the need of a server.