不使用javax.Mail如何计算fetch RFC822.SIZE字段值
RFC 1064 协议下 FETCH 命令
RFC822.SIZE 字段计算方法 字段本质定义
RFC822.SIZE的取值是符合RFC822规范的完整邮件原始报文的字节总数,这个值是给客户端做邮件大小展示、下载进度计算、断点续传偏移判断用的,要求精度100%,不能有字节级误差。
具体实现规则
- 计数基准为纯RFC822邮件报文的二进制字节流,覆盖范围必须包含三部分:
- 完整的邮件头区域(所有头字段、头字段内部的折叠换行都要算)
- 邮件头和正文之间的空分隔行(即单独的
\r\n行) - 完整的邮件正文区域(包含所有MIME分段头、MIME边界分隔符、base64/Quoted-Printable编码后的附件内容、最后一级MIME的结束边界
--xxx--)
- 必须避开的错误计算逻辑:
- 不要对原始报文做任何转码、解码、内容裁剪后计数:比如不要把base64附件解码成原文件算大小,不要删除冗余头字段,不要去掉MIME分隔线
- 不要把你的服务端自定义存储的元数据算进去:比如你在数据库里给邮件加的UID、存储路径、用户标签这类非RFC822标准的内容,全部排除
- 不要按字符数计数:多字节编码(比如UTF-8的中文头、中文正文)要按实际占用的字节数算,不能按Unicode字符个数算
- 换行符特殊处理
IMAP协议要求邮件传输统一使用CRLF(\r\n,即字节0x0D 0x0A)作为换行符:- 如果你存储的邮件原始流本身就是标准CRLF换行,直接返回流的总字节数即可
- 如果你存储时做了空间优化,把所有CRLF归一化成了单个LF(
\n,字节0x0A),返回SIZE前要补算所有LF对应的CR字节长度,公式为:最终SIZE = LF格式存储的报文总字节数 + 报文中LF字符的总个数
参考实现伪代码
/** * 计算RFC822.SIZE返回值 * @param rawStoredMail 服务端存储的原始邮件二进制字节 * @param isCrlfStored 存储时是否使用标准CRLF换行 * @return 符合RFC1064要求的RFC822.SIZE值 */ long calcRfc822Size(byte[] rawStoredMail, boolean isCrlfStored) { if (isCrlfStored) { return rawStoredMail.length; } // 统计LF数量补算CR字节 long lfCnt = 0; for (byte b : rawStoredMail) { if (b == 0x0A) { lfCnt++; } } return rawStoredMail.length + lfCnt; }
校验标准
你实际通过FETCH命令返回完整RFC822报文内容时,传输的邮件实体总字节数必须和你返回的RFC822.SIZE值完全相等,否则客户端会判定报文截断、解析失败。
内容的提问来源于stack exchange,提问作者Ahmad Yhia
相关产品推荐
相关产品推荐

