13

I've been trying for days now to send mail from Grails application and unsuccessfully. I'm using:

  • grails 1.3.7
  • mail 1.0 plugin
  • spring-security-core 1.2.6 plugin
  • tomcat 7.0.23

Specifficaly I'm trying to send mail with Exchange from application deployed on Tomcat server trought port 25 with no authentication, no SSL.

I've tried to send message with telnet from the VMWare virtual machine on which the app is deployed and it got trough.

This is my class for sending mails:

public boolean sendMessage(String to, String msgSubject, String msgText) 
{
    String host = "mail.mydomain.com";
    String username = "myuser@mydomain.com"; // your authsmtp username
    String password = "mypassword" // your authsmtp password
    String from = "myuser@mydomain.com";

    Properties props = System.getProperties();
    props.put("mail.smtp.host", host);
    props.put("mail.smtp.user", username);
    props.put("mail.smtp.password", password);
    props.put("mail.smtp.port", "25"); // thish is the port recommended by authsmtp
    props.put("mail.smtp.auth", "false");

    Session session = Session.getDefaultInstance(props, null);
    MimeMessage message = new MimeMessage(session);
    message.setFrom(new InternetAddress(from));

    InternetAddress to_address = new InternetAddress(to);
    message.addRecipient(Message.RecipientType.TO, to_address);

    message.setSubject(msgSubject);
    message.setText(msgText);
    Transport transport = session.getTransport("smtp");
    transport.connect(host, username, password);
    transport.sendMessage(message, message.getAllRecipients());
    transport.close();
    return true;
}

This is error stack trace:

javax.mail.AuthenticationFailedException: No authentication mechansims supported by both server and client

at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:590)

at javax.mail.Service.connect(Service.java:291)

at javax.mail.Service.connect(Service.java:172)

at javax.mail.Service$connect.call(Unknown Source)

at org.helpdesk.MymailService.sendMessage(MymailService.groovy:37)

at org.helpdesk.MymailService$sendMessage.call(Unknown Source)

at org.helpdesk.RequestController$_closure13.doCall(RequestController.groovy:247)

at org.helpdesk.RequestController$_closure13.doCall(RequestController.groovy)

at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.lang.Thread.run(Unknown Source)

I've read few dozen posts considering problems like this but I've still havent manage to solve the problem. Any help is appreciated.

*EDIT:*Is it possible that there are some problems sending mails using javaMail with Exchange server SMTP when there is no authentication?

Vadzim
  • 24,954
  • 11
  • 143
  • 151
drago
  • 1,207
  • 4
  • 24
  • 45
  • You should configure all the properties like "mail.smtp.host" in `Config.groovy` – Dónal Dec 23 '11 at 11:51
  • @Don But how to tell my SendMessage method to take mail configuration options from Config.groovy? – drago Dec 23 '11 at 12:30
  • Should I do some configuring on Tomcat to enable emailing? – drago Dec 23 '11 at 14:14
  • The mail plugin automatically takes the settings from Config.groovy. You do not need to do any Tomcat configuration. Have you read the docs for the mail plugin? – Dónal Dec 23 '11 at 14:16
  • @Don Yes. I've read the documents but still I can't make it work. Maybe I've overlooked something considering Exchange server configuration. I've managed to send mail using Gmail with no trouble. But using company's Exchange server no luck at all. So I've been chasing my tail for some time now. – drago Dec 23 '11 at 14:25
  • if you've managed to send email using Gmail the problem must be specific to the exchange config. I don't know anything about that, sorry. – Dónal Dec 23 '11 at 14:36
  • The error message `No authentication mechansims supported by both server and client` tells you, that the server does not support anonymous sending of mails. Are you sure the test with your virtual machine worked with the exchange server? – Chris Dec 23 '11 at 16:07
  • Try changing to smtp authentication and that might work `props.put("mail.smtp.auth", "true");` – First Zero Dec 23 '11 at 16:09
  • @crudolf Well, I've menagged to send mail with telnet from that VM. I guess the next step is to ask admin to activate authentication on exchange. But I generaly don't understand why would authentication would be off. – drago Dec 26 '11 at 10:35
  • @FirstZero I've tried that, but as I said my admin told me that authentication is off on Exchange server. Either the setting for Exchange are wrong or javaMail is having some problem with sending mails via SMTP from Exchange server. – drago Dec 26 '11 at 10:38

6 Answers6

22

in my case, I had to set the property

"mail.smtp.ehlo"

to "false"

(in addition to adding to setting the property "mail.smtp.auth" to "false" which however seems to be the default according to this link)

Before setting "mail.smtp.ehlo" to "false" I saw the following debug output (enabled by setting the property "mail.debug" to "true"):

DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM 
DEBUG SMTP: mechanism LOGIN not supported by server
DEBUG SMTP: mechanism PLAIN not supported by server
DEBUG SMTP: mechanism DIGEST-MD5 not supported by server
DEBUG SMTP: mechanism NTLM not supported by server

and then getting the same javax.mail.AuthenticationFailedException.

(in this case, the SMTP server was a Microsoft one)

Andre Holzner
  • 18,333
  • 6
  • 54
  • 63
  • 1
    Be careful - when setting the true/false, `"true"` is different from `true`! (The quoted forms seem to work!). – vektor Nov 21 '17 at 07:39
  • 1
    mail.smtp.ehlo=false (no need for quotes) worked for me for StreamSets – Jamby Jan 24 '18 at 13:41
20

If you're trying to connect to your mail server without authentication, call the connect method that doesn't take a username and password. If you pass it a username and password, it thinks you really want to authenticate, and since it can't find an authentication mechanism that the server supports, it fails.

Bill Shannon
  • 29,579
  • 6
  • 38
  • 40
  • Thanks that was the solution for my application! Edit: this is a bugfix since javamail 1.4.3 see https://java.net/projects/javamail/lists/dev/archive/2014-01/message/3 – Stefan Höltker Jul 05 '16 at 13:00
  • Thanks, this save me a lot, I have been battling with this for a week now. Finally! – Jelil Adesina Aug 08 '16 at 10:34
  • Thanks. It worked for me. But it is very stupid although mail.smtps.auth=false, why it is trying to connect username and password? – Zafer Jan 25 '18 at 04:11
  • Why are you passing a user name and password if you don’t want JavaMail to use them? :-) – Bill Shannon Jan 25 '18 at 04:17
3

Well it looks that I had few problems. At first, Exchange wasn't setup correctly. And then it seems I've tried all possible configurations but the right one. This works:

class MymailService 
{
    boolean transactional = false

    public sendMessage(String to, String cc, String msgSubject, String msgText) 
    {
        String host = "mail.mailserver.com";
        String username = "myusername@mymailserver.com"; 
        String password = "xxx"; 
        String from = "myusername@mymailserver.com";
        String port = "25";

        Properties props = System.getProperties();
        props.put("mail.smtp.host", host);
        props.put("mail.smtp.port", port); 
        props.put("mail.smtp.auth", "false");

        Transport transport = null;

        try{
            Session session = Session.getDefaultInstance(props, null);
            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(from));

        InternetAddress to_address = new InternetAddress(to);
        message.addRecipient(Message.RecipientType.TO, to_address);

        InternetAddress cc_address = new InternetAddress(cc);
        message.addRecipient(Message.RecipientType.CC, cc_address);

        message.setSubject(msgSubject);
        message.setText(msgText);

        transport = session.getTransport("smtp");
        transport.connect();
        transport.sendMessage(message, message.getAllRecipients());
    } finally {
        if (transport != null) try { transport.close(); } catch (MessagingException logOrIgnore){}
    }
}
}

The final clue was Bill Shannon's post. Thanks Bill!

drago
  • 1,207
  • 4
  • 24
  • 45
1
  1. Check if the server you are hitting mandates an authentication or not. more on this in the code.

  2. Do put a mail.debug in the properties to know what exactly is going on between your code and the mailserver. more on this in the code.

Here is a simple code that works well for me with my company's mail server:

 package com.datereminder.service;

 import java.util.Properties;
 import javax.mail.Message;
 import javax.mail.MessagingException;
 import javax.mail.PasswordAuthentication;
 import javax.mail.Session;
 import javax.mail.Transport;
 import javax.mail.internet.InternetAddress;
 import javax.mail.internet.MimeMessage;

 public class ReminderDaemonService2 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Properties props = new Properties();
        props.put("mail.smtp.host", "mail.mycompany123.com");
 // this mandates authentication at the mailserver
        props.put("mail.smtp.auth", "true");
 // this is for printing debugs

        props.put("mail.debug", "true");

        Session session = Session.getDefaultInstance(props,
            new javax.mail.Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication("sadique.khan@mycompany123.com","xxxxxxxxxxx");
                }
            });

        try {

            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress("sadique.khan@mycompany123.com"));
            message.setRecipients(Message.RecipientType.TO,
                    InternetAddress.parse("my.bestfriend@mycompany123.com"));
            message.setSubject("Testing Subject");
            message.setText("Dear Friend," +
                    "\n\n This is a Test mail!");

            Transport.send(message);

        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }
    }
 }
svarog
  • 9,477
  • 4
  • 61
  • 77
Sadique Khan
  • 161
  • 3
  • 13
0

Here's my solution, maybe it's not the best way, but it works for me...

in the mail-config.xml:

<bean id="mailSender" class="com.xxx.service.MailSender">
    <property name="host" value="${mail.host}" />
    <property name="port" value="${mail.port}" />
    <property name="protocol" value="${mail.protocol}" />
    <property name="defaultEncoding" value="UTF-8" />
    <property name="authRequired" value="${mail.auth}" />
    <property name="username" value="${mail.username}" />
    <property name="password" value="${mail.password}" />
    <property name="javaMailProperties">
        <props>
            <prop key="mail.smtps.auth">${mail.auth}</prop>
        </props>
    </property>
</bean>

and here's the setting:

mail.from=XXX Team <xxx@tricascade.com>
mail.host=exchange.xxx.com
mail.port=25
mail.protocol=smtp
mail.auth=false
mail.username=
mail.password=

and finally, the code:

package com.xxx.service;
import org.springframework.mail.javamail.JavaMailSenderImpl;

public class MailSender extends JavaMailSenderImpl {

    private boolean authRequired;

    @Override
    public String getUsername() {
        if (!authRequired) {
            return null;
        }
        return super.getUsername();
    }

    @Override
    public String getPassword() {
        if (!authRequired) {
            return null;
        }
        return super.getPassword();
    }

    public boolean isAuthRequired() {
        return authRequired;
    }

    public void setAuthRequired(boolean authRequired) {
        this.authRequired = authRequired;
    }

}
0

If you'd want your application that to login to the SMTP server (Since you are providing authentication details). Just change

props.put("mail.smtp.auth", false); 

to

props.put("mail.smtp.auth", true); 
svarog
  • 9,477
  • 4
  • 61
  • 77
Rohin
  • 516
  • 3
  • 7
  • 20