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



在我的小项目中,我想设置"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"值,其中包含"+10xxx

"。

如何设置与 DATA 中的"收件人"标头不匹配的"RCPT TO"值?

我刚刚看了一下源代码MimeMessageHelper你会发现setTo()函数都调用javax.mail.Message#setRecipient,就像你在使用帮助程序之前执行命令一样。

我看到两种使用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 的弹簧包装器:

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);
        }
    }
}

将邮件发送到"RCPT 收件人"地址并在邮件中包含其他"收件人"地址而不实际将邮件发送到其他"收件人"的技巧是使用message.send(message, InternetAddress) 而不是 message.send(message)并在 message.setRecipients 中设置其他"收件人"

下面是代码片段:

Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
InternetAddress[] addresses = new InternetAddress[recipientaddresstoshowinmail];
message.setRecipients(Message.RecipientType.TO, addresses);         
message.setSubject(subject);
message.setText(body);
InternetAddress[] toaddress = new InternetAddress[] {new InternetAddress(to)};          
**Transport.send(message, actualtoaddress);**

最新更新