cms
当前位置:首页->常见问题
java语言开发使用阿里云邮箱发邮件的功能(支持附件)
  • 作者:本站
  • 日期:2022-10-10
  • 出处:totcms
  • 点击:29
package job.tot.util;

import java.io.UnsupportedEncodingException;
import java.util.*;

import javax.mail.*;
import javax.mail.internet.*;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;

import java.security.Security;
import job.tot.bean.MailBean;
import job.tot.exception.BadInputException;
import job.tot.filter.DisableHtmlTagFilter;
import job.tot.global.Sysconfig;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public final class MailUtils {

    public static final int MAX_MESSAGES_PER_TRANSPORT = 100;
    public static final boolean useSSL = true;
    private static Log log = LogFactory.getLog(MailUtils.class);

    private MailUtils() {// prevent instantiation
    }

    //private static MailOptions mailOption = new MailOptions();
    /**
     * Get the user name part of an email. Ex: input: test@yahoo.com => output:
     * test
     *
     * @param email String the email
     * @return String the user name part of an email
     */
    public static String getEmailUsername(String email) {
        if (email == null) {
            return "";
        }
        int atIndex = email.indexOf('@');
        if (atIndex == -1) {
            return "";
        }
        return email.substring(0, atIndex);
    }

    /**
     * Get the domain part of an email. Ex: input: test@yahoo.com => output:
     * yahoo.com
     *
     * @param email String the email
     * @return String the user name part of an email
     */
    public static String getEmailDomain(String email) {
        if (email == null) {
            return "";
        }
        int atIndex = email.indexOf('@');
        if (atIndex == -1) {
            return "";
        }
        return email.substring(atIndex + 1);
    }

    /**
     * Check if an email is good and safe or not. This method should be use for
     * all email input from user
     *
     * @param input String
     * @throws BadInputException if email is not good
     */
    public static void checkGoodEmail(String input) throws BadInputException {
        if (input == null) {
            throw new BadInputException("Sorry, null string is not a good email.");//@todo : localize me
        }
        int atIndex = input.indexOf('@');
        int dotIndex = input.lastIndexOf('.');
        if ((atIndex == -1) || (dotIndex == -1) || (atIndex >= dotIndex)) {
            //@todo : localize me
            throw new BadInputException("Error: '" + DisableHtmlTagFilter.filter(input) + "' is not a valid email value. Please try again.");
        }

        // now check for content of the string
        int length = input.length();
        char c = 0;

        for (int i = 0; i < length; i++) {
            c = input.charAt(i);
            if ((c >= 'a') && (c <= 'z')) {
                // lower char
            } else if ((c >= 'A') && (c <= 'Z')) {
                // upper char
            } else if ((c >= '0') && (c <= '9')/* && (i != 0)*/) {
                // as of 31 Jan 2004, i relax the email checking
                // so that the email can start with an numeric char
                // hopefully it does not introduce a security bug
                // because this value will be inserted into sql script

                // numeric char
            } else if (((c == '_') || (c == '-') || (c == '.') || (c == '@')) && (i != 0)) {
                // _ char
            } else {
                // not good char, throw an BadInputException
                //@todo : localize me
                throw new BadInputException(input + " is not a valid email. Reason: character '" + c + "' is not accepted in an email.");
            }
        }// for

        // last check
        try {
            new javax.mail.internet.InternetAddress(input);
        } catch (Exception ex) {
            log.error("Error when running checkGoodEmail", ex);
            throw new BadInputException("Assertion: dont want to occur in Util.checkGoodEmail");
        }
    }

    /**
     * 使用加密的方式,利用465端口进行传输邮件,开启ssl
     *
     * @param to 为收件人邮箱

     * @param message 发送的消息

     * @param bcc 暗抄送

     * @param fileList发送的附件


     */
    public static int sendEmailSSL(String from, String to, String cc, String bcc, String subject, String message, String fileList[]) {
         int ifcg=0;
        try {
            Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
            final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
            //设置邮件会话参数
            Properties props = new Properties();
            int ports = Sysconfig.getMailServerPort();
            //邮箱的发送服务器地址
            props.setProperty("mail.smtp.host", Sysconfig.getMailServer());
            props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
            props.setProperty("mail.smtp.socketFactory.fallback", "false");
            //邮箱发送服务器端口,这里设置为465端口
            props.setProperty("mail.smtp.port", String.valueOf(ports));
            props.setProperty("mail.smtp.socketFactory.port", String.valueOf(ports));
            props.put("mail.smtp.auth", "true");
            final String username = Sysconfig.getMailUserName();
            final String password = Sysconfig.getMailPassword();
            //获取到邮箱会话,利用匿名内部类的方式,将发送者邮箱用户名和密码授权给jvm
            Session session = Session.getDefaultInstance(props, new Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });
            //通过会话,得到一个邮件,用于发送
            Message msg = new MimeMessage(session);
            //设置发件人
            msg.setFrom(new InternetAddress(from));
//            msg.setSubject(MimeUtility.encodeText(subject, "UTF-8", "B"));
//            msg.setContent(message, "text/html;charset=UTF-8");
            //设置收件人,to为收件人,cc为抄送,bcc为密送
            msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to, false));
            msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc, false));
            msg.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(bcc, false));
            msg.setSubject(subject);
            //设置邮件消息
            //msg.setText(message);
            MimeBodyPart messageBodyPart = new MimeBodyPart();
            messageBodyPart.setText(message);
            messageBodyPart.setHeader("Content-Type", "text/html;charset=GBK");

            //messageBodyPart.setHeader("Content-Transfer-Encoding", "quoted-printable");
            MimeMultipart multipart = new MimeMultipart();
            multipart.addBodyPart(messageBodyPart);
            // 2.保存多个附件
            if (fileList != null) {
                addTach(fileList, multipart);
            }
            multipart.setSubType("mixed");
            msg.setContent(multipart);
            msg.saveChanges();
            //设置发送的日期
            msg.setSentDate(new Date());

            //调用Transport的send方法去发送邮件
//            Transport.send(msg);
            Transport.send(msg, msg.getAllRecipients());

        } catch (Exception e) {
            ifcg=1;
            e.printStackTrace();
        }
        return ifcg;
    }

    // 添加多个附件
    public static void addTach(String fileList[], Multipart multipart)
            throws MessagingException, UnsupportedEncodingException {
        for (int index = 0; index < fileList.length; index++) {
            MimeBodyPart mailArchieve = new MimeBodyPart();
            FileDataSource fds = new FileDataSource(fileList[index]);
            mailArchieve.setDataHandler(new DataHandler(fds));
            mailArchieve.setFileName(MimeUtility.encodeText(fds.getName(),
                    "GBK", "B"));
            multipart.addBodyPart(mailArchieve);
        }
    }

    /**
     * NOTE: param to, cc, bcc cannot be all empty. At least one must have a
     * valid value
     *
     * @param from : must be a valid email. However, if this param is null, then
     * the default mail in config file will be use
     * @param to : can be null
     * @param cc : can be null
     * @param bcc: can be null
     * @param subject
     * @param message
     * @throws MessagingException
     * @throws BadInputException
     */
    public static void sendMail(String from, String to, String cc, String bcc, String subject, String message)
            throws MessagingException, BadInputException, UnsupportedEncodingException {

        MailBean mailItem = new MailBean();
        mailItem.setFrom(from);
        mailItem.setTo(to);
        mailItem.setCc(cc);
        mailItem.setBcc(bcc);
        mailItem.setSubject(subject);
        mailItem.setMessage(message);

        sendMail(mailItem);
    }

    public static void sendMail(MailBean mailItem)
            throws MessagingException, BadInputException, UnsupportedEncodingException {

        ArrayList mailList = new ArrayList(1);
        mailList.add(mailItem);
        try {
            sendMail(mailList);
        } catch (MessagingException mex) {
            log.error("MessagingException has occured.", mex);
            log.debug("MessagingException has occured. Detail info:");
            log.debug("from = " + mailItem.getFrom());
            log.debug("to = " + mailItem.getTo());
            log.debug("cc = " + mailItem.getCc());
            log.debug("bcc = " + mailItem.getBcc());
            log.debug("subject = " + mailItem.getSubject());
            log.debug("message = " + mailItem.getMessage());
            throw mex;// this may look redundant, but it is not :-)
        }
    }

    public static void sendMail(Collection mailStructCollection)
            throws MessagingException, BadInputException, UnsupportedEncodingException {

        Session session = null;
        Transport transport = null;
        int totalEmails = mailStructCollection.size();
        int count = 0;
        int sendFailedExceptionCount = 0;

        String server = "";
        String userName = "";
        String password = "";
        int port = 25;

        boolean useMailsource = Sysconfig.isUseMailSource();

        try {
            for (Iterator iter = mailStructCollection.iterator(); iter.hasNext();) {
                count++;

                if ((transport == null) || (session == null)) {
                    if (useMailsource) {
                        try {
                            InitialContext ic = new InitialContext();
                            // mailSourceName = "java:comp/env/mail/mailSession";
                            String mailSourceName = Sysconfig.getMailSourceName();
                            log.debug("MailUtil : use mailsource = " + mailSourceName);
                            session = (Session) ic.lookup("java:comp/env/" + mailSourceName);
                            transport = session.getTransport("smtp");
                        } catch (NamingException e) {
                            log.error("Cannot get Mail session", e);
                            throw new MessagingException("Cannot get the mail session from JNDI. Send mail failed.");
                        }
                    } else {// does not use datasourse
                        Properties props = new Properties();

                        server = Sysconfig.getMailServer();
                        port = Sysconfig.getMailServerPort();
                        userName = Sysconfig.getMailUserName();
                        password = Sysconfig.getMailPassword();

                        props.put("mail.smtp.host", server);
                        props.put("mail.smtp.port", String.valueOf(port));
                        if ((userName != null) && (userName.length() > 0)) {
                            props.put("mail.smtp.auth", "true");
                        }
                        //props.put("mail.debug", "true");
                        session = Session.getDefaultInstance(props, null);
                        transport = session.getTransport("smtp");
                    }// end of does not use datasource

                    if ((userName != null) && (userName.length() > 0)) {
                        transport.connect(server, userName, password);
                    } else {
                        transport.connect();
                    }
                }

                MailBean mailItem = (MailBean) iter.next();

                String from = mailItem.getFrom();
                String to = mailItem.getTo();
                String cc = mailItem.getCc();
                String bcc = mailItem.getBcc();
                String subject = mailItem.getSubject();
                String message = mailItem.getMessage();

                //if (from == null) from = mailOption.defaultMailFrom;
                if (from == null) {
                    from = Sysconfig.getDefaultMailFrom();
                }

                try {
                    // this will also check for email error
                    checkGoodEmail(from);
                    InternetAddress fromAddress = new InternetAddress(from);
                    InternetAddress[] toAddress = getInternetAddressEmails(to);
                    InternetAddress[] ccAddress = getInternetAddressEmails(cc);
                    InternetAddress[] bccAddress = getInternetAddressEmails(bcc);
                    if ((toAddress == null) && (ccAddress == null) && (bccAddress == null)) {
                        //@todo : localize me
                        throw new BadInputException("Cannot send mail since all To, Cc, Bcc addresses are empty.");
                    }

                    // create a message
                    MimeMessage msg = new MimeMessage(session);
                    msg.setSentDate(new Date());
                    msg.setFrom(fromAddress);

                    if (toAddress != null) {
                        msg.setRecipients(Message.RecipientType.TO, toAddress);
                    }
                    if (ccAddress != null) {
                        msg.setRecipients(Message.RecipientType.CC, ccAddress);
                    }
                    if (bccAddress != null) {
                        msg.setRecipients(Message.RecipientType.BCC, bccAddress);
                    }
                    //This code is use to display unicode in Subject
                    //msg.setSubject(MimeUtility.encodeText(subject, "iso-8859-1", "Q"));
                    //msg.setText(message);
                    //String content = new String(message.getBytes(""), "UTF-8");
                    msg.setSubject(subject, "UTF-8");
                    //msg.setText(message, "UTF-8");

                    /*
                     //Below code is use for unicode*/
                    MimeBodyPart messageBodyPart = new MimeBodyPart();
                    messageBodyPart.setText(message);
                    messageBodyPart.setHeader("Content-Type", "text/html;charset=gbk");
                    //messageBodyPart.setHeader("Content-Transfer-Encoding", "quoted-printable");
                    MimeMultipart multipart = new MimeMultipart();
                    multipart.addBodyPart(messageBodyPart);
                    msg.setContent(multipart);

                    msg.saveChanges();

                    transport.sendMessage(msg, msg.getAllRecipients());

                    // now check if sent 100 emails, then close connection (transport)
                    if ((count % MAX_MESSAGES_PER_TRANSPORT) == 0) {
                        try {
                            if (transport != null) {
                                transport.close();
                            }
                        } catch (MessagingException ex) {
                        }
                        transport = null;
                        session = null;
                    }

                } catch (SendFailedException ex) {
                    sendFailedExceptionCount++;
                    log.error("SendFailedException has occured.", ex);
                    log.warn("SendFailedException has occured. Detail info:");
                    log.warn("from = " + from);
                    log.warn("to = " + to);
                    log.warn("cc = " + cc);
                    log.warn("bcc = " + bcc);
                    log.warn("subject = " + subject);
                    log.info("message = " + message);
                    if ((totalEmails != 1) && (sendFailedExceptionCount > 10)) {
                        throw ex;// this may look redundant, but it is not :-)
                    }
                } catch (MessagingException mex) {
                    log.error("MessagingException has occured.", mex);
                    log.warn("MessagingException has occured. Detail info:");
                    log.warn("from = " + from);
                    log.warn("to = " + to);
                    log.warn("cc = " + cc);
                    log.warn("bcc = " + bcc);
                    log.warn("subject = " + subject);
                    log.info("message = " + message);
                    throw mex;// this may look redundant, but it is not :-)
                }
            }//for
        } finally {
            try {
                if (transport != null) {
                    transport.close();
                }
            } catch (MessagingException ex) {
            }
            if (totalEmails != 1) {
                log.info("sendMail: totalEmails = " + totalEmails + " sent count = " + count);
            }
        }
    }

    /**
     * This method trim the email variable, so if it contains only spaces, then
     * it will be empty string, then we have 0 token :-) The returned value is
     * never null
     */
    public static String[] getEmails(String email) throws BadInputException {
        if (email == null) {
            email = "";
        }
        email = email.trim();// very important
        email = email.replace(',', ';');// replace all occurrence of ',' to ';'
        StringTokenizer t = new StringTokenizer(email, ";");
        String[] ret = new String[t.countTokens()];
        int index = 0;
        while (t.hasMoreTokens()) {
            String mail = t.nextToken().trim();
            checkGoodEmail(mail);
            ret[index] = mail;
            //log.debug(ret[index]);
            index++;
        }
        return ret;
    }

    public static String[] getEmails(String to, String cc, String bcc) throws BadInputException {
        String[] toMail = getEmails(to);
        String[] ccMail = getEmails(cc);
        String[] bccMail = getEmails(bcc);
        String[] ret = new String[toMail.length + ccMail.length + bccMail.length];
        int index = 0;
        for (int i = 0; i < toMail.length; i++) {
            ret[index] = toMail[i];
            index++;
        }
        for (int i = 0; i < ccMail.length; i++) {
            ret[index] = ccMail[i];
            index++;
        }
        for (int i = 0; i < bccMail.length; i++) {
            ret[index] = bccMail[i];
            index++;
        }
        return ret;
    }

    /**
     * This method will return null if there is not any email
     *
     * @param email
     * @return
     * @throws BadInputException
     * @throws AddressException
     */
    private static InternetAddress[] getInternetAddressEmails(String email)
            throws BadInputException, AddressException {
        String[] mails = getEmails(email);
        if (mails.length == 0) {
            return null;// must return null, not empty array
        }
        //log.debug("to = " + mails);
        InternetAddress[] address = new InternetAddress[mails.length];
        for (int i = 0; i < mails.length; i++) {
            address[i] = new InternetAddress(mails[i]);
            //log.debug("to each element = " + mails[i]);
        }
        return address;
    }

}