通过SMTP协议和Exchange两种方式实现邮件的发送功能

作者简介:
🌹 作者:暗夜91
🤟 个人主页:暗夜91的主页
📝 微信公众号: 程序员的知识站 ,关注本人公众号,学习更多前沿知识。


SpringBoot通过smtp协议和exchange两种不同方式实现邮件的发送功能。

1、SMTP协议与Exchange

SMTP协议:

SMTP的全称是 “Simple Mail Transfer Protocol”,即简单邮件传输协议。它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式。它的一个重要特点是它能够在传送中接力传送邮件,即邮件可以通过不同网络上的主机接力式传送。

SMTP认证,简单地说就是要求必须在提供了账户名和密码之后才可以登录SMTP服务器,这就使得那些垃圾邮件的散播者无可乘之机。增加SMTP认证的目的是为了使用户避免受到垃圾邮件的侵扰。SMTP已是事实上的E-Mail传输的标准。

Exchange

Exchange是微软公司推出的一套电子邮件处理组件,同样是通过smtp协议进行邮件的收发。

2、添加SMTP邮件发送的依赖

<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>mail</artifactId>
    <version>1.4.7</version>
</dependency>

3、添加Exchange协议依赖

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

4、添加邮件配置

#smtp协议配置
smtp.send.address=xxx@163.com
smtp.send.password=BSNLVRFYDUMBJYNF
smtp.send.host=smtp.163.com

#exchange协议配置
exchange.send.address=bigdata@xxx.com
exchange.send.password=Abc123456
exchange.send.host=mail.xxx.com

5、添加公共接口

package com.lll.common.mail;

import lombok.extern.slf4j.Slf4j;
import microsoft.exchange.webservices.data.core.ExchangeService;
import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
import microsoft.exchange.webservices.data.core.enumeration.property.BodyType;
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.FileAttachment;
import microsoft.exchange.webservices.data.property.complex.MessageBody;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.*;

@Slf4j
@Component
public class MailCommonService {

    /**
     *
     * @param toList 收件人列表
     * @param mailSubject 邮件主题
     * @param contentList 邮件正文,会按照列表的顺序,在邮件中显示。
     *                    邮件内容有多行时,每行内容是一个MailContentVO
     * @param fileList 附件文件绝对路径
     * @param type 邮件协议类型
     */
    public void sendMail(List<String> toList,String mailSubject,List<MailContentVO> contentList,List<String> fileList,MailProtocolType type) {
        try {
            Properties props = new Properties();
            ClassPathResource classPathResource = new ClassPathResource("/mail.properties");
            InputStream inputStream  = classPathResource.getInputStream();
            props.load(new InputStreamReader(inputStream, "UTF-8"));
            if (type.equals(MailProtocolType.smtp)){
                sendMailSmtp(toList,mailSubject,contentList,fileList,props);
            } else if(type.equals(MailProtocolType.exchange)){
                sendMailExchange(toList,mailSubject,contentList,fileList,props);
            } else {
                sendMailSmtp(toList,mailSubject,contentList,fileList,props);
            }
            log.info("邮件发送完成......");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 发送邮件
     * @param toList 收件人列表
     * @param mailSubject 邮件主题
     * @param contentList 邮件正文,会按照列表的顺序,在邮件中显示。
 *                    邮件内容有多行时,每行内容是一个MailContentVO
     * @param fileList 附件文件绝对路径
     * @param properties 发送邮箱相关配置
     */
    public void sendMailSmtp(List<String> toList, String mailSubject, List<MailContentVO> contentList, List<String> fileList, Properties properties) {
        String senderAddress = properties.getProperty("smtp.send.address");
        String senderPassword = properties.getProperty("smtp.send.password");
        try {
            //1、连接邮件服务器的参数配置
            Properties props = new Properties();
            //设置用户的认证方式
            props.setProperty("mail.smtp.auth", "true");
            //设置传输协议
            props.setProperty("mail.transport.protocol", "smtp");
            //设置发件人的SMTP服务器地址
            props.setProperty("mail.smtp.host", properties.getProperty("smtp.send.host"));
            //2、创建定义整个应用程序所需的环境信息的 Session 对象
            Session session = Session.getInstance(props);
            //设置调试信息在控制台打印出来
            session.setDebug(true);
            //3、创建邮件的实例对象
            Message msg = getMimeMessage(session,senderAddress,toList,mailSubject,contentList,fileList);
            //4、根据session对象获取邮件传输对象Transport
            Transport transport = session.getTransport();
            //设置发件人的账户名和密码
            transport.connect(senderAddress, senderPassword);
            //发送邮件,如果只想发送给指定的人,可以如下写法
            Address[] addresses = new Address[toList.size()];
            for (int i=0;i<toList.size();i++){
                addresses[i] = new InternetAddress(toList.get(i));
            }
            transport.sendMessage(msg, addresses);
            //5、关闭邮件连接
            transport.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private MimeMessage getMimeMessage(Session session, String senderAddress, List<String> toList, String mailSubject, List<MailContentVO> contentList, List<String> fileList) throws Exception {
        //1、创建一封邮件的实例对象
        MimeMessage msg = new MimeMessage(session);
        //2、设置发件人地址
        msg.setFrom(new InternetAddress(senderAddress));
        /**
         * 3、设置收件人地址(可以增加多个收件人、抄送、密送),即下面这一行代码书写多行
         * MimeMessage.RecipientType.TO:发送
         * MimeMessage.RecipientType.CC:抄送
         * MimeMessage.RecipientType.BCC:密送
         */
        for (String to:toList){
            msg.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(to));
        }
        //4、设置邮件主题
        msg.setSubject(mailSubject, "UTF-8");

        // 5、(文本+图片)设置 文本 和 图片"节点"的关系(将 文本 和 图片"节点"合成一个混合"节点")
        MimeMultipart mm_text_image = new MimeMultipart();

        //文本节点的内容组合
        List<String> textContent = new ArrayList<>();
        for (MailContentVO vo:contentList){
            MailContentType type = vo.getType();
            if (type.equals(MailContentType.txt)){
                textContent.add(vo.getContent());
            }else{
                String uid = UUID.randomUUID().toString();
                //创建图片"节点"
                MimeBodyPart image = new MimeBodyPart();
                //读取本地文件
                DataHandler dh = new DataHandler(new FileDataSource(vo.getContent()));
                //将图片数据添加到"节点"
                image.setDataHandler(dh);
                //为"节点"设置一个唯一编号(在文本"节点"将引用该ID)
                image.setContentID(uid);
                mm_text_image.addBodyPart(image);
                //
                String img = "<img src='cid:"+uid+"'/>";
                textContent.add(img);
            }
        }

        MimeBodyPart text = new MimeBodyPart();
        // 这里添加图片的方式是将整个图片包含到邮件内容中, 实际上也可以以 http 链接的形式添加网络图片
        text.setContent(StringUtils.join(textContent,"<br/>"), "text/html;charset=UTF-8");
        mm_text_image.addBodyPart(text);
        mm_text_image.setSubType("related"); //关联关系

        // 8. 将 文本+图片 的混合"节点"封装成一个普通"节点"
        // 最终添加到邮件的 Content 是由多个 BodyPart 组成的 Multipart, 所以我们需要的是 BodyPart,
        MimeBodyPart text_image = new MimeBodyPart();
        text_image.setContent(mm_text_image);

        MimeMultipart mm = new MimeMultipart();
        mm.addBodyPart(text_image);
        //9、设置附件
        for (String filePath:fileList){
            File file = new File(filePath);
            MimeBodyPart attachment = new MimeBodyPart();
            DataSource source = new FileDataSource(filePath);
            attachment.setDataHandler(new DataHandler(source));
            attachment.setFileName(MimeUtility.encodeText(file.getName()));
            mm.addBodyPart(attachment);
        }
        mm.setSubType("mixed");  // 混合关系
        // 10、 设置整个邮件的关系(将最终的混合"节点"作为邮件的内容添加到邮件对象)
        msg.setContent(mm);
        //设置邮件的发送时间,默认立即发送
        msg.setSentDate(new Date());
        return msg;
    }

    /**
     * 发送邮件
     * @param toList 收件人列表
     * @param subject 邮件主题
     * @param contentList 邮件正文,会按照列表的顺序,在邮件中显示。
     *                    邮件内容有多行时,每行内容是一个MailContentVO
     * @param filePath 附件文件绝对路径
     * @param properties 发送邮箱相关配置
     */
    private void sendMailExchange(List<String> toList, String subject, List<MailContentVO> contentList, List<String> filePath, Properties properties)  {
        ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
        ExchangeCredentials credentials = new WebCredentials(properties.getProperty("exchange.send.address"),properties.getProperty("exchange.send.password"));
        service.setCredentials(credentials);
        try {
	        String uri = "https://"+properties.getProperty("exchange.send.host")+"/ews/exchange.asmx";
            service.setUrl(new URI(uri));
            EmailMessage msg = new EmailMessage(service);
            //设置邮件主题
            msg.setSubject(subject);

            //设置邮件正文
            List<String> textContent = new ArrayList<>();
            for (MailContentVO vo:contentList){
                MailContentType type = vo.getType();
                if (type.equals(MailContentType.txt)){
                    textContent.add(vo.getContent());
                }else{
                    String uid = UUID.randomUUID().toString();
                    FileAttachment attachment = msg.getAttachments().addFileAttachment(vo.getContent());
                    attachment.setContentType("image");
                    attachment.setContentId(uid);
                    String img = "<img src='cid:"+uid+"'/>";
                    textContent.add(img);
                }
            }

            //设置邮件附件
            if (!CollectionUtils.isEmpty(filePath)){
                for (String path:filePath){
                    String uid = UUID.randomUUID().toString();
                    FileAttachment attachment1 = msg.getAttachments().addFileAttachment(path);
                    attachment1.setContentType("image");
                    attachment1.setContentId(uid);
                }
            }
            MessageBody body = MessageBody.getMessageBodyFromText(StringUtils.join(textContent,"<br/>")+"<hr/>");
            body.setBodyType(BodyType.HTML);
            msg.setBody(body);

            //设置邮件收件人
            for (String to : toList) {
                msg.getToRecipients().add(to);
            }

            //邮件发送
            msg.send();
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
    }
}

6、支持协议枚举

public enum MailProtocolType {
    smtp,exchange;
}

7、邮件正文内容枚举

public enum MailContentType {
    txt("文本"),img("图片");
    private String type;
    MailContentType(String type) {
        this.type = type;
    }
}

8、邮件正文内容

@Data
public class MailContentVO {

    /**
     * 正文信息类型
     */
    private MailContentType type;

    /**
     * 正文信息
     * txt内容或img绝对路径
     */
    private String content;

}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Python可以使用smtplib和poplib模块来实现基于SMTP和POP3协议邮件发送小程序。首先,我们需要使用smtplib模块来连接到SMTP服务器,并通过SMTP协议发送邮件。接着,我们可以使用poplib模块来连接到POP3服务器,通过POP3协议接收邮件。 我们可以使用以下的步骤来实现这个小程序: 1. 导入smtplib和poplib模块 2. 设置SMTP服务器的主机和端口,例如`smtp_server = 'smtp.example.com'`,`smtp_port = 25` 3. 连接到SMTP服务器,例如`smtp_conn = smtplib.SMTP(smtp_server, smtp_port)` 4. 登录到SMTP服务器,例如`smtp_conn.login('username', 'password')` 5. 设置发件人、收件人和邮件内容,例如`from_addr = 'sender@example.com'`,`to_addr = 'recipient@example.com'`,`message = 'This is a test email'` 6. 发送邮件,例如`smtp_conn.sendmail(from_addr, to_addr, message)` 7. 关闭与SMTP服务器的连接,例如`smtp_conn.quit()` 对于接收邮件部分,我们也可以使用以下步骤: 1. 设置POP3服务器的主机和端口,例如`pop_server = 'pop.example.com'`,`pop_port = 110` 2. 连接到POP3服务器,例如`pop_conn = poplib.POP3(pop_server, pop_port)` 3. 登录到POP3服务器,例如`pop_conn.user('username')`,`pop_conn.pass_('password')` 4. 获取邮件列表,例如`num_messages = len(pop_conn.list()[1])` 5. 获取并打印邮件内容,例如`for i in range(num_messages): print(pop_conn.retr(i+1))` 6. 关闭与POP3服务器的连接,例如`pop_conn.quit()` 通过这个Python小程序,我们可以实现基于SMTP和POP3协议邮件发送和接收功能

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暗夜91

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值