JavaMail - 如何设置与 DATA 中的 “RCPT TO:” header 不匹配的 SMTP “To:”

标签 java spring email jakarta-mail

在我的小项目中,我想设置“RCPT TO”和“To”,如下所示:

RCPT TO: <user-signup-123123123@bounces.example.com>
DATA
354  Go ahead vw9sm7458976pbc.68 - gsmtp
Date: Thu, 02 Mar 2012 14:06:02 +0200 (ICT)
To: +10xxxxxxxxxx

我尝试使用以下代码

JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost("HOST");
mailSender.setPort("PORT");
mailSender.setUsername("USERNAME");
mailSender.setPassword("PASSWORD");

MimeMessage mimeMessage = mailSender.createMimeMessage();

try {
    mimeMessage.setRecipient(MimeMessage.RecipientType.TO, 
        new InternetAddress("user-signup-123123123@bounces.example.com"));

    MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
    helper.setTo("+10xxxxxxxxxx");

} catch(Exception e) {
     System.out.println(e.getMessage());
}

还有我得到的日志

MAIL FROM:<abc@xxxxx.com>
250 2.1.0 OK x5sm16625925pbw.26 - gsmtp
RCPT TO:<user-signup-123123123@bounces.example.com>
250 2.1.5 OK x5sm16625925pbw.26 - gsmtp
RCPT TO:<+10xxxxxxxxxx>

如您所见,程序创建了一个新的“RCPT TO”值,其中包含“+10xxxxxxxxxx”。

如何设置与 DATA 中的“To” header 不匹配的“RCPT TO”值?

最佳答案

我刚刚看了source code of MimeMessageHelper您将看到 setTo() 函数都调用 javax.mail.Message#setRecipient,就像您在使用 Helper 之前执行的命令一样。

我看到两种使用 JavaMail 的解决方案:

扩展 MimeMessage 并覆盖 getAllRecipients(),因为此方法用于确定 JavaMailImpl 中的收件人

// yes you need to use this package as SmartMimeMessage is package-private or you loose spring advantages
package org.springframework.mail.javamail;

import javax.activation.FileTypeMap;
import javax.mail.Address;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;

/**
 * Created for http://stackoverflow.com/q/22860793/1266906
 */
public class RoutedSmartMimeMessage extends SmartMimeMessage {
    private Address[] rcptTo = null;

    /**
     * Create a new SmartMimeMessage.
     *
     * @param session
     *         the JavaMail Session to create the message for
     * @param defaultEncoding
     *         the default encoding, or {@code null} if none
     * @param defaultFileTypeMap
     *         the default FileTypeMap, or {@code null} if none
     */
    public RoutedSmartMimeMessage(final Session session,
                                  final String defaultEncoding,
                                  final FileTypeMap defaultFileTypeMap) {
        super(session, defaultEncoding, defaultFileTypeMap);
    }

    public Address[] getRcptTo() {
        return rcptTo;
    }

    public void setRcptTo(final Address... rcptTo) {
        this.rcptTo = rcptTo;
    }

    @Override
    public Address[] getAllRecipients() throws MessagingException {
        if(rcptTo != null) {
            return rcptTo;
        } else {
            return super.getAllRecipients();
        }
    }

    public static MimeMessage createMesage(final JavaMailSenderImpl javaMailSender) {
        return new SmartMimeMessage(javaMailSender.getSession(), javaMailSender.getDefaultEncoding(), javaMailSender.getDefaultFileTypeMap());
    }
}

编写自己的发送方法并使用Transport#sendMessage(javax.mail.Message, javax.mail.Address[])直接

基于 JavaMail 的 spring 包装器:

import org.springframework.mail.MailAuthenticationException;
import org.springframework.mail.MailException;
import org.springframework.mail.MailSendException;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Created for http://stackoverflow.com/q/22860793/1266906
 */
public class Mailing {
    public static void main(String[] args) {
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        mailSender.setHost("HOST");
        mailSender.setPort(25);
        mailSender.setUsername("USERNAME");
        mailSender.setPassword("PASSWORD");

        MimeMessage mimeMessage = mailSender.createMimeMessage();

        try {
            /*
            Not needed
            mimeMessage.setRecipient(MimeMessage.RecipientType.TO,
                                     new InternetAddress("user-signup-123123123@bounces.example.com"));
             */

            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
            helper.setTo("+10xxxxxxxxxx");

            sendMail(mailSender, mimeMessage, new InternetAddress("user-signup-123123123@bounces.example.com"));

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    /**
     * Adopted from {@link org.springframework.mail.javamail.JavaMailSenderImpl#doSend(javax.mail.internet.MimeMessage[], Object[])} to be able to call {@link javax.mail.Transport#send(javax.mail.Message, javax.mail.Address[])} with a different second parameter than {@link javax.mail.Message#getAllRecipients() mimeMessage.getAllRecipients()}
     *
     * @param javaMailSender
     *         JavaMailSender object holding configuration options
     * @param mimeMessage
     *         MimeMessage object to send
     * @param realRecipients
     *         RCPT TO: sddresses
     * @throws org.springframework.mail.MailAuthenticationException
     *         in case of authentication failure
     * @throws org.springframework.mail.MailSendException
     *         in case of failure when sending a message
     */
    private static void sendMail(final JavaMailSenderImpl javaMailSender,
                                 final MimeMessage mimeMessage,
                                 final Address... realRecipients) throws MailException {
        final Map<Object, Exception> failedMessages = new LinkedHashMap<Object, Exception>();

        final Transport transport;
        try {
            Session session = javaMailSender.getSession();
            String protocol = javaMailSender.getProtocol();
            if (protocol == null) {
                protocol = session.getProperty("mail.transport.protocol");
                if (protocol == null) {
                    protocol = JavaMailSenderImpl.DEFAULT_PROTOCOL;
                }
            }
            transport = session.getTransport(protocol);
            transport.connect(javaMailSender.getHost(),
                              javaMailSender.getPort(),
                              javaMailSender.getUsername(),
                              javaMailSender.getPassword());
        } catch (AuthenticationFailedException ex) {
            throw new MailAuthenticationException(ex);
        } catch (MessagingException ex) {
            failedMessages.put(mimeMessage, ex);
            throw new MailSendException("Mail server connection failed", ex, failedMessages);
        }

        try {
            try {
                if (mimeMessage.getSentDate() == null) {
                    mimeMessage.setSentDate(new Date());
                }
                String messageId = mimeMessage.getMessageID();
                mimeMessage.saveChanges();
                if (messageId != null) {
                    // Preserve explicitly specified message id...
                    mimeMessage.setHeader("Message-ID", messageId);
                }
                transport.sendMessage(mimeMessage, realRecipients);
            } catch (MessagingException ex) {
                failedMessages.put(mimeMessage, ex);
            }
        } finally {
            try {
                transport.close();
            } catch (MessagingException ex) {
                if (!failedMessages.isEmpty()) {
                    throw new MailSendException("Failed to close server connection after message failures", ex,
                                                failedMessages);
                } else {
                    throw new MailSendException("Failed to close server connection after message sending", ex);
                }
            }
        }

        if (!failedMessages.isEmpty()) {
            throw new MailSendException(failedMessages);
        }
    }
}

关于JavaMail - 如何设置与 DATA 中的 “RCPT TO:” header 不匹配的 SMTP “To:”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22860793/

相关文章:

java - 如何使用 REST 调用返回 List<MyObject>?

java - Spring 套应用中的 yarn 配置

Spring AMQP 恢复器无法与 SimpleMessageListenerContainer 一起使用

C# 将电子邮件 'from' 地址更改为用户提供的地址

php - 如何使用 mailgun 批量发送带附件的邮件?

java - 如何将当前客户端目录添加到日志文件名中?

java - Lambda 表达式,如何在自定义方法中将方法作为参数传递

java - 如何使用 GSON 忽略对象列表中对象内部的 transient 字段定义

使用 JAXB 实现 Spring Restful Web 服务的基于 Java 的配置

email - 使用Google Apps设置无回复的电子邮件地址