关于邮件MIME协议和java mail 发送邮件-程序员宅基地

  写这篇博客主要是由于前两天上线一个邮箱的代码,接收方一直解析不了。由于对MIME协议这一块不是很了解,比对了很长时间才发现从我们程序传过去的MimeMessage是符合MIME规范的,接收方无法解析是由于提供邮件服务的smtp在给通过程序发送的邮件写入内容无received域,还有一些内容不符合MIME规范,无法通过接收方domino服务器的解析规则。

一 MIME协议

1.介绍

MIME, 全称为“Multipurpose Internet Mail Extensions”, 比较确切的中文名称为“多用途互联网邮件扩展”。它是当前广泛应用的一种电子邮件技术规范,基本内容定义于RFC 2045-2049(注意RFC1521和RFC1522是它的过时版本)。


2.MIME邮件头的域

 

3.中文转码

    在邮件里写入的值如果是中文的话是需要进行转码的,比如说Subject域写入的主题,有附件的话filename的值,由于我这边使用的是java mail的方式发送邮件,使用的是MimeUtility的encodeText方法自动转码的,这种方法可以在2,3参数指定使用的文字编码和使用BASE 64还是QP进行转码。不指定的话转码方式会根据参数1的字符转成ascii码去判断使用BASE 64还是QP进行转码。

   转码后出来的是=?UTF-8?B?heWuuS5kb2M=?= 这样的一个格式。UTF-8是文字的编码,B指BASE 64,如果是Q的话就是指QP。=?UTF-8?B?之后的内容就是你文字的内容,比如说主题名,附件名。

 

二 java mail 发送邮件

 这里直接贴代码上来吧,java mail的写法还是很清晰的

public static void sendMail(
			String sendSMTPHost,
			String sendSMTPPort,
			String sendMailAccount,
			String sendMailPass,
			List<String> recipients,
			String subject,
			String content,
			List<String> attachmentNames)throws Exception{
		//1.创建用于连接服务器的参数配置
		Properties props = new Properties();
		props.put("mail.transport.protocol", "smtp");//使用的协议(JavaMail规范要求)
		props.put("mail.smtp.host",sendSMTPHost);//发件人邮箱的SMTP服务器地址
		props.put("mail.smtp.auth", "true");//需要请求认证
		
		//2.根据配置创建会话对象,用于和邮件服务器交互
		Session session = Session.getInstance(props);
		session.setDebug(true);//设置为debug模式,可以查看详细的发送log
		
		//3.创建一封邮件
		MimeMessage message = createMimeMessage(session,sendMailAccount,recipients,subject,content,attachmentNames);
		
		//4.根据Session获取邮件传输对象
		Transport transport = session.getTransport();
		
		//5.使用邮箱账号和密码连接邮件服务器,这里认证的邮箱必须与message中发件人邮箱一致
		transport.connect(sendMailAccount, sendMailPass);
		
		//6.发送邮件,发到所有收件地址
		transport.sendMessage(message, message.getAllRecipients());
		
		//7.关闭连接
		transport.close();
	}


private static MimeMessage createMimeMessage(
			Session session,
			String sendMailAccount, 
			List<String> recipients, 
			String subject,
			String content, 
			List<String> attachmentNames)throws Exception{
		
		//1.创建一封邮件
		MimeMessage message = new MimeMessage(session);
		
		//2.From:发件人
		message.setFrom(new InternetAddress(sendMailAccount));
		
		//3.TO:收件人 (CC:代表抄送。BCC:代表暗送接收者。)
		String toAddressStr = JavaStringUtil.connectListToString(recipients, ",");
		InternetAddress[] toAddressList = new InternetAddress().parse(toAddressStr);
		message.setRecipients(MimeMessage.RecipientType.TO,toAddressList);
		
		//4.Subject:主题
		message.setSubject(MimeUtility.encodeText(subject, "UTF-8","B"));
		
		//5.Content:正文
		Multipart multipart = new MimeMultipart();//创建正文"节点"
		MimeBodyPart text = new MimeBodyPart();
		text.setContent(content,"text/plain;charset=UTF-8");
		multipart.addBodyPart(text);
		
		//6.附件
		for(String fileName : attachmentNames){
			MimeBodyPart adjunct = new MimeBodyPart();
			DataHandler dh = new DataHandler(new FileDataSource(fileName));//读取集合中的文件
			adjunct.setDataHandler(dh);//将附件数据添加到"节点"
			if(dh.getName().contains("txt")){
				adjunct.setHeader("Content-Type", "text/plain; charset=UTF-8");
				}else if(dh.getName().contains("doc")){
					adjunct.setHeader("Content-Type", "application/msword; charset=UTF-8");

				}
			
			
			adjunct.setFileName(MimeUtility.encodeText(dh.getName()));//设置附件的文件名
		
			multipart.addBodyPart(adjunct);
		}
		
		message.setContent(multipart);//设置正文
		
		//7.设置发件时间
		message.setSentDate(new Date());
		
		//8.保存设置
		message.saveChanges();
		
		return message;
	}
	

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_37654153/article/details/83416517

智能推荐

踩坑记录---线程池拒绝策略引起的一系列巧合_org.springframework.amqp.amqpresourcenotavailablee-程序员宅基地

文章浏览阅读629次。一、业务场景1、定时任务从数据库搜索一批需要处理的数据,大概在140w左右2、140w数据使用循环处理3、循环中,将数据处理任务提交到线程池(坑一),并在任务中,把处理结果推送到mq4、定时任务结束二、异常现象在执行循环到过程中,突然循环中断,任务处理失败,循环提前结束三、代码贴图主线程简化版代码如下// 获取全部需要处理的任务数据 List<T> needHandlerList = getNeedHandlerList(shardingContext); _org.springframework.amqp.amqpresourcenotavailableexception: the channelmax l

Html5 注释_h5注释-程序员宅基地

文章浏览阅读1.8k次,点赞2次,收藏4次。定义注释标签用于在源文档中插入注释。注释会被浏览器忽略。可使用注释对您的代码进行解释,这样做有助于自己和别人在以后对代码的编辑和理解。用法 <!-- 注释内容 --><html> <body> <!-- this is the comment , do not show in the browser,but can be view in the source code --> 只显示内容,没有头部信息。 <!-- 注释,不在浏览_h5注释

【数据结构与算法基础】二叉搜索树和平衡二叉树_二叉搜索树一定是二叉平衡树吗-程序员宅基地

文章浏览阅读918次。写在前面今天学习在排序和查找中都很有用的特殊二叉树,平衡二叉树和搜索二叉树。相关代码实现已上传至Github:data_structure/Tree/1.二叉搜索树(Binary Search Tree)二叉搜索时是一种对排序和查找都很有用的特殊二叉树。其或者是一棵空树;或者是具有以下性质的二叉树:若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值 若右子树不空,..._二叉搜索树一定是二叉平衡树吗

python中123+5.0的执行结果_wtfpython-cn/README.md at master · witglory/wtfpython-cn · GitHub-程序员宅基地

文章浏览阅读451次。What the f*ck Python! ????一些有趣且鲜为人知的 Python 特性. Python, 是一个设计优美的解释型高级语言, 它提供了很多能让程序员感到舒适的功能特性. 但有的时候, Python 的一些输出结果对于初学者来说似乎并不是那么一目了然.这个有趣的项目意在收集 Python 中那些难以理解和反人类直觉的例子以及鲜为人知的功能特性, 并尝试讨论这些现象背后真正的原理!虽然..._python中123+5.0的执行结果

C# 文本编码转换-程序员宅基地

文章浏览阅读3.2k次。1. C#的编码转换默认由System.Text.Encoding进行操控转换.引用为: using System.Text;2. C# Encoding类自带编码有:UTF7/UTF8/UTF32/Unicode/ASCII,Encoding类有一个子类就是Default,此类会随操作环境变化而变化,在Windows平台上编码为"GB18030" (GBK为此编码子...

linux下的source命令及~/.bashrc, ~/.bash_profile详解_source ~/.bashrc-程序员宅基地

文章浏览阅读1.1w次,点赞8次,收藏62次。刚登录Linux时,首先启动 /etc/profile 文件,然后再启动用户目录下的 ~/.bash_profile、 ~/.bash_login或 ~/.profile文件中的其中一个,source命令通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录。_source ~/.bashrc

随便推点

浅谈Canvas与SVG_canvas svg 缩放 性能-程序员宅基地

文章浏览阅读3.5k次,点赞2次,收藏5次。1、SVGSVG 可缩放矢量图形(Scalable Vector Graphics),是一种使用可扩展标记语言(XML)描述2D图形的语言。SVG严格遵从XML语法,并用文本格式的描述性语言来描述图像内容,因此是一种和图像分辨率无关的矢量图形格式。SVG基于XML,意味着SVG DOM中的每个元素都是可用的,可以为某个元素附加 JavaScript 事件处理器。在SVG中,每个被绘制的_canvas svg 缩放 性能

编写程序接收一个ASCII码(从0至128),然后显示输入ASCII码所代表的字符。 注意: (1)能够对1个或多个输入的ASCII码进行处理; (2)对于输入的非ASCII码进行判定和排除。_显示ascii码程序-程序员宅基地

文章浏览阅读6.3k次。import java.util.*;public class Demo3 { /** * @param args */ /* * 编写程序接收一个ASCII码(从0至128),然后显示输入ASCII码所代表的字符。注意:(1)能够对1个或多个输入的ASCII码进行处理;(2)对于输入的非ASCII码进行判定和排除。_显示ascii码程序

windows系统批量启动应用bat脚本_批量运行bat-程序员宅基地

文章浏览阅读3.9k次,点赞7次,收藏18次。每次电脑自动重启之后,就要从新打开各种软件。所以就想自己写一个bat脚本,批量启动自己想启动的各个应用服务。@echo off::启动 webstorm64echo start webstorm64call start /d "D:\Program Files\JetBrains\WebStorm 2020.2.1\bin" webstorm64.exe::暂停几秒再执行后面的 命令ping -n 5 127.1 >nul 2>nulecho webstorm6..._批量运行bat

德卡斯特(deCasteljau)递推公式绘制Bezier曲线_decasteljau递推算法代码-程序员宅基地

文章浏览阅读1.3k次。德卡斯特(deCasteljau)递推公式绘制Bezier曲线德卡斯特递推算法比使用定义算法绘图简单了很多,已经成为绘制Bezier曲线的标准算法;参考上一篇文章添加下面代码: CP2 PP[4][4];//德卡斯特递推数组 void deCasteljau(double t);//德卡斯特递推计算 void DrawdeCasteljauBezier(CDC*pDC);//绘制德卡斯特曲线void CdrawBezierCurveView::deCasteljau(double t){_decasteljau递推算法代码

关于远程桌面登陆提示“连接被拒绝,因为没有授权此用户账号进行远程登录”_域用户 连接被拒绝,因为没有授权此用户账户进行远程登陆-程序员宅基地

文章浏览阅读1.2w次。分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 继续跟着教材做实验。在_域用户 连接被拒绝,因为没有授权此用户账户进行远程登陆

Android源码分析之拍照、图片、录音、视频和音频功能_安卓实现 相机功能 录音拍照视频-程序员宅基地

文章浏览阅读624次。From:Android源码分析之拍照、图片、录音、视频和音频功能 //选择图片 requestCode 返回的标识Intent innerIntent = new Intent(Intent.ACTION_GET_CONTENT); //"android.intent.action.GET_CONTENT"innerIntent.setType(con_安卓实现 相机功能 录音拍照视频

推荐文章

热门文章

相关标签