问题 如何使用MS Exchange服务器发送电子邮件


我正在尝试使用我公司的邮件服务器发送电子邮件。但我得到以下例外

Caused by: com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.1 Client was not authenticated
    at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:1388)
    at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:959)
    at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:583)
    at javax.mail.Transport.send0(Transport.java:169)
    at javax.mail.Transport.send(Transport.java:98)

这是我的示例代码,

Properties props = System.getProperties();

// Setup mail server
props.put("mail.smtp.host", "example.server.com");
props.put("mail.smtp.auth", "true");
props.put("mail.debug", "true");
props.put("mail.smtp.port", "25");
// Get session
//Session session = Session.getDefaultInstance(props, null);
Session session = Session.getDefaultInstance(props,
    new javax.mail.Authenticator() {
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication("username", "password");
        }
    });

// Define message
MimeMessage message = new MimeMessage(session);

// Set the from address
message.setFrom(new InternetAddress(from));

// Set the to address
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));

// Set the subject
message.setSubject("Hello JavaMail");

// Set the content
message.setText("Welcome to JavaMail");

// Send message
Transport.send(message);

什么代码错了? 与用户名和密码一样,我使用的是公司的电子邮件地址和密码。


1589
2018-01-13 15:23


起源



答案:


5.7.1可能是由交换而不是您的代码引起的。您可能只需要在服务器上启用中继。对于匿名用户或来自某个IP地址。我不是交易所的专家,但我之前有这个工作。这是我测试的最后一个解决方案:

如果在用户通过身份验证时尝试通过SMTP在Exchange服务器上发送电子邮件时遇到5.7.1错误。

对于ref,您刚刚遇到的问题是由Exchange 2007服务器上的设置引起的 - 这在2003服务器上通常不会出现问题

修正如下...

您可以通过GUI设置此身份验证设置

  • 在服务器配置/集线器传输/默认<ServerName>中
  • 右键单击,属性,权限组
  • 选中“匿名用户”,然后单击“确定”

显然,匿名用户不是太安全,但你可以看到这是否解决了这个问题。


6
2018-01-13 15:26



我的IT管理员是否可以在Exchange服务器上创建一个测试用户并且可以用来发送电子邮件? - user509755
我不明白为什么不。我的网络应用程序在模拟连接到Exchange服务器的域用户的情况下运行。我不太了解交换,但安装应用程序的最后一个站点必须允许从Web服务器通过smtp中继。在此之后我停止了5.7.1错误。如果你不能做一个用户,那么你应该能够至少做一台机器。这里有一些关于单个用户无法中继哪个有一些有趣信息的问题的信息 social.technet.microsoft.com/Forums/en-US/exchangesvrtransport/... - WraithNath
我认为你需要寻找的领域是'接收连接器' - WraithNath
感谢WraithNath的宝贵意见。我将使用一个测试用户发送所有电子邮件。但我也通过在gmail上创建一个用户并使用此用户发送消息来测试我的应用程序并且工作正常。但我的最终目标是使用公司的邮件服务器。你的帮助给了我非常宝贵的意见。 - user509755


答案:


5.7.1可能是由交换而不是您的代码引起的。您可能只需要在服务器上启用中继。对于匿名用户或来自某个IP地址。我不是交易所的专家,但我之前有这个工作。这是我测试的最后一个解决方案:

如果在用户通过身份验证时尝试通过SMTP在Exchange服务器上发送电子邮件时遇到5.7.1错误。

对于ref,您刚刚遇到的问题是由Exchange 2007服务器上的设置引起的 - 这在2003服务器上通常不会出现问题

修正如下...

您可以通过GUI设置此身份验证设置

  • 在服务器配置/集线器传输/默认<ServerName>中
  • 右键单击,属性,权限组
  • 选中“匿名用户”,然后单击“确定”

显然,匿名用户不是太安全,但你可以看到这是否解决了这个问题。


6
2018-01-13 15:26



我的IT管理员是否可以在Exchange服务器上创建一个测试用户并且可以用来发送电子邮件? - user509755
我不明白为什么不。我的网络应用程序在模拟连接到Exchange服务器的域用户的情况下运行。我不太了解交换,但安装应用程序的最后一个站点必须允许从Web服务器通过smtp中继。在此之后我停止了5.7.1错误。如果你不能做一个用户,那么你应该能够至少做一台机器。这里有一些关于单个用户无法中继哪个有一些有趣信息的问题的信息 social.technet.microsoft.com/Forums/en-US/exchangesvrtransport/... - WraithNath
我认为你需要寻找的领域是'接收连接器' - WraithNath
感谢WraithNath的宝贵意见。我将使用一个测试用户发送所有电子邮件。但我也通过在gmail上创建一个用户并使用此用户发送消息来测试我的应用程序并且工作正常。但我的最终目标是使用公司的邮件服务器。你的帮助给了我非常宝贵的意见。 - user509755


Mail.jar(版本1.4.0)与MS Exchange Server和throws存在兼容性问题 530 5.7.1 Client was not authenticated,即使配置了用户名和密码。

将邮件API升级到1.4.4或1.4.7应该可以解决此问题。

Mail API的1.4.7可以从以下URL下载: http://www.oracle.com/technetwork/java/javamail/index.html


2
2018-06-16 10:18





在某些公司中,Exchange服务器SMTP支持是禁用的,您无法要求它们启用它。在这些情况下,合理的解决方案是这样的:

http://davmail.sourceforge.net/


2
2017-09-27 23:56





简单的Java邮件 为我工作。你唯一需要检查的是正确的 主机名用户名港口 和 密码  TransportStrategy.SMTP_TLS

new Mailer(host, port, username, password, TransportStrategy.SMTP_TLS).sendMail(email);

1
2018-03-06 11:29



@zeddam是开源使用的吗? - Sundhar


当我使用MS Exhange SMTP Server发送电子邮件时,我使用上面的maven依赖项。

<dependency>
    <groupId>com.microsoft.ews-java-api</groupId>
    <artifactId>ews-java-api</artifactId>
    <version>2.0</version>
</dependency>

出于这个原因,我创建了一个代表MS Exchange Server的电子邮件客户端的类。我使用log4j进行日志记录。

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

在MS Exchange客户端类下面(我使用构建器模式构建对象以确保线程安全),

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import microsoft.exchange.webservices.data.core.ExchangeService;
import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
import microsoft.exchange.webservices.data.core.exception.service.local.ServiceLocalException;
import microsoft.exchange.webservices.data.core.service.item.EmailMessage;
import microsoft.exchange.webservices.data.credential.ExchangeCredentials;
import microsoft.exchange.webservices.data.credential.WebCredentials;
import microsoft.exchange.webservices.data.property.complex.MessageBody;
import org.apache.log4j.Logger;

/**
 * A client to connect to a MS Exchange SMTP Server.
 */
public final class ExchangeClient {

    private static final Logger LOGGER = Logger.getLogger(ExchangeClient.class);

    private final String hostname;
    private final ExchangeVersion exchangeVersion;
    private final String domain;
    private final String username;
    private final String password;
    private final String subject;
    private final String recipientTo;
    private final List<String> recipientCc;
    private final List<String> recipientBcc;
    private final List<String> attachments;
    private final String message;

    private ExchangeClient(ExchangeClientBuilder builder) {
        this.hostname = builder.hostname;
        this.exchangeVersion = builder.exchangeVersion;
        this.domain = builder.domain;
        this.username = builder.username;
        this.password = builder.password;
        this.subject = builder.subject;
        this.recipientTo = builder.recipientTo;
        this.recipientCc = builder.recipientCc;
        this.recipientBcc = builder.recipientBcc;
        this.attachments = builder.attachments;
        this.message = builder.message;
    }

    public static class ExchangeClientBuilder {

        private String hostname;
        private ExchangeVersion exchangeVersion;
        private String domain;
        private String username;
        private String password;
        private String subject;
        private String recipientTo;
        private List<String> recipientCc;
        private List<String> recipientBcc;
        private List<String> attachments;
        private String message;

        public ExchangeClientBuilder() {
            this.exchangeVersion = ExchangeVersion.Exchange2010_SP1;
            this.hostname = "";
            this.username = "";
            this.password = "";
            this.subject = "";
            this.recipientTo = "";
            this.recipientCc = new ArrayList<>(0);
            this.recipientBcc = new ArrayList<>(0);
            this.attachments = new ArrayList<>(0);
            this.message = "";
        }

        /**
         * The hostname of the Exchange Web Service. It will be used for
         * connecting with URI https://hostname/ews/exchange.asmx
         *
         * @param hostname the hostname of the MS Exchange Smtp Server.
         * @return the builder for chain usage.
         */
        public ExchangeClientBuilder hostname(String hostname) {
            this.hostname = hostname;
            return this;
        }

        /**
         * The Exchange Web Server version.
         *
         * @param exchangeVersion the Exchange Web Server version.
         * @return the builder for chain usage.
         */
        public ExchangeClientBuilder exchangeVersion(ExchangeVersion exchangeVersion) {
            this.exchangeVersion = exchangeVersion;
            return this;
        }

        /**
         * The domain of the MS Exchange Smtp Server.
         *
         * @param domain the domain of the Active Directory. The first part of
         * the username. For example: MYDOMAIN\\username, set the MYDOMAIN.
         * @return the builder for chain usage.
         */
        public ExchangeClientBuilder domain(String domain) {
            this.domain = domain;
            return this;
        }

        /**
         * The username of the MS Exchange Smtp Server. The second part of the
         * username. For example: MYDOMAIN\\username, set the username.
         *
         * @param username the username of the MS Exchange Smtp Server.
         * @return the builder for chain usage.
         */
        public ExchangeClientBuilder username(String username) {
            this.username = username;
            return this;
        }

        /**
         * The password of the MS Exchange Smtp Server.
         *
         * @param password the password of the MS Exchange Smtp Server.
         * @return the builder for chain usage.
         */
        public ExchangeClientBuilder password(String password) {
            this.password = password;
            return this;
        }

        /**
         * The subject for this send.
         *
         * @param subject the subject for this send.
         * @return the builder for chain usage.
         */
        public ExchangeClientBuilder subject(String subject) {
            this.subject = subject;
            return this;
        }

        /**
         * The recipient for this send.
         *
         * @param recipientTo the recipient for this send.
         * @return the builder for chain usage.
         */
        public ExchangeClientBuilder recipientTo(String recipientTo) {
            this.recipientTo = recipientTo;
            return this;
        }

        /**
         * You can specify one or more email address that will be used as cc
         * recipients.
         *
         * @param recipientCc the first cc email address.
         * @param recipientsCc the other cc email address for this send.
         * @return the builder for chain usage.
         */
        public ExchangeClientBuilder recipientCc(String recipientCc, String... recipientsCc) {
            // Prepare the list.
            List<String> recipients = new ArrayList<>(1 + recipientsCc.length);
            recipients.add(recipientCc);
            recipients.addAll(Arrays.asList(recipientsCc));
            // Set the list.
            this.recipientCc = recipients;
            return this;
        }

        /**
         * You can specify a list with email addresses that will be used as cc
         * for this email send.
         *
         * @param recipientCc the list with email addresses that will be used as
         * cc for this email send.
         * @return the builder for chain usage.
         */
        public ExchangeClientBuilder recipientCc(List<String> recipientCc) {
            this.recipientCc = recipientCc;
            return this;
        }

        /**
         * You can specify one or more email address that will be used as bcc
         * recipients.
         *
         * @param recipientBcc the first bcc email address.
         * @param recipientsBcc the other bcc email address for this send.
         * @return the builder for chain usage.
         */
        public ExchangeClientBuilder recipientBcc(String recipientBcc, String... recipientsBcc) {
            // Prepare the list.
            List<String> recipients = new ArrayList<>(1 + recipientsBcc.length);
            recipients.add(recipientBcc);
            recipients.addAll(Arrays.asList(recipientsBcc));
            // Set the list.
            this.recipientBcc = recipients;
            return this;
        }

        /**
         * You can specify a list with email addresses that will be used as bcc
         * for this email send.
         *
         * @param recipientBcc the list with email addresses that will be used
         * as bcc for this email send.
         * @return the builder for chain usage.
         */
        public ExchangeClientBuilder recipientBcc(List<String> recipientBcc) {
            this.recipientBcc = recipientBcc;
            return this;
        }

        /**
         * You can specify one or more email address that will be used as cc
         * recipients.
         *
         * @param attachment the first attachment.
         * @param attachments the other attachments for this send.
         * @return the builder for chain usage.
         */
        public ExchangeClientBuilder attachments(String attachment, String... attachments) {
            // Prepare the list.
            List<String> attachmentsToUse = new ArrayList<>(1 + attachments.length);
            attachmentsToUse.add(attachment);
            attachmentsToUse.addAll(Arrays.asList(attachments));
            // Set the list.
            this.attachments = attachmentsToUse;
            return this;
        }

        /**
         * You can specify a list with email attachments that will be used for
         * this email send.
         *
         * @param attachments the list with email attachments that will be used
         * for this email send.
         * @return the builder for chain usage.
         */
        public ExchangeClientBuilder attachments(List<String> attachments) {
            this.attachments = attachments;
            return this;
        }

        /**
         * The body of the email message.
         *
         * @param message the body of the email message.
         * @return the builder for chain usage.
         */
        public ExchangeClientBuilder message(String message) {
            this.message = message;
            return this;
        }

        /**
         * Build a mail.
         *
         * @return an EmailApacheUtils object.
         */
        public ExchangeClient build() {
            return new ExchangeClient(this);
        }
    }

    public boolean sendExchange() {
        // The Exchange Server Version.
        ExchangeService exchangeService = new ExchangeService(exchangeVersion);

        // Credentials to sign in the MS Exchange Server.
        ExchangeCredentials exchangeCredentials = new WebCredentials(username, password, domain);
        exchangeService.setCredentials(exchangeCredentials);

        // URL of exchange web service for the mailbox.
        try {
            exchangeService.setUrl(new URI("https://" + hostname + "/ews/Exchange.asmx"));
        } catch (URISyntaxException ex) {
            LOGGER.error("An exception occured while creating the uri for exchange service.", ex);
            return false;
        }

        // The email.
        EmailMessage emailMessage;
        try {
            emailMessage = new EmailMessage(exchangeService);
            emailMessage.setSubject(subject);
            emailMessage.setBody(MessageBody.getMessageBodyFromText(message));
        } catch (Exception ex) {
            LOGGER.error("An exception occured while setting the email message.", ex);
            return false;
        }

        // TO recipient.
        try {
            emailMessage.getToRecipients().add(recipientTo);
        } catch (ServiceLocalException ex) {
            LOGGER.error("An exception occured while sstting the TO recipient(" + recipientTo + ").", ex);
            return false;
        }

        // CC recipient.
        for (String recipient : recipientCc) {
            try {
                emailMessage.getCcRecipients().add(recipient);
            } catch (ServiceLocalException ex) {
                LOGGER.error("An exception occured while sstting the CC recipient(" + recipient + ").", ex);
                return false;
            }
        }

        // BCC recipient
        for (String recipient : recipientBcc) {
            try {
                emailMessage.getBccRecipients().add(recipient);
            } catch (ServiceLocalException ex) {
                LOGGER.error("An exception occured while sstting the BCC recipient(" + recipient + ").", ex);
                return false;
            }
        }

        // Attachements.
        for (String attachmentPath : attachments) {
            try {
                emailMessage.getAttachments().addFileAttachment(attachmentPath);
            } catch (ServiceLocalException ex) {
                LOGGER.error("An exception occured while setting the attachment.", ex);
                return false;
            }
        }

        try {
            emailMessage.send();
            LOGGER.debug("An email is send.");
        } catch (Exception ex) {
            LOGGER.error("An exception occured while sending an email.", ex);
            return false;
        }

        return true;
    }

}

一个工作的例子,

// import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
ExchangeClient client = new ExchangeClient.ExchangeClientBuilder()
        .hostname("webmail.domainOfWeb.com")
        .exchangeVersion(ExchangeVersion.Exchange2010)
        .domain("ActiveDirectoryDomain")
        .username("ActiveDirectoryUsername")
        .password("ActiveDirectoryPassword")
        .recipientTo("recipient@whatever.com")
        .recipientCc("recipient@whatever.com") // Ignore it in case you will not use Cc recipients.
        .recipientBcc("recipient@whatever.com") // Ignore it in case you will not use Bcc recipients.
        .attachments("/home/username/image.png") // Ignore it in case you will not use attachements.
        .subject("Test Subject")
        .message("Test Message")
        .build();
client.sendExchange();

1
2017-10-12 23:31





我不得不使用javamail + exchange。返回的消息很无奈。 感谢堆栈,我得到了一些提示。

将其添加到您的代码中

  props.put("mail.smtp.starttls.enable","true");

考虑添加使用的机器的证书。 要找到它们,只需转到浏览器,导出它们并导入到 cacerts文件 正在使用。


1
2017-12-23 14:07





请使用以下代码部分代替 Transport.send(message);

MimeMessage message = new MimeMessage(session);

message.saveChanges();
Transport transport = session.getTransport("smtp");
transport.connect(host, "user", "pwd");
transport.sendMessage(message, message.getAllRecipients());
transport.close();

我在当地进行了测试,它正在运行


0
2017-08-16 21:38



Transport.send(message) 方法包括 message.saveChanges(), transport.connect, transport.sendMessage 和 transport.close  所以我不认为自己需要再做一次。 - omerhakanbilici