LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

Jmail接收邮件及UTF-8解码问题(含VB及C#代码)

admin
2011年12月22日 12:30 本文热度 3143


Jmail接收到的邮件,如果标题的编码方式是UTF-8的话,直接从Base64解码出来的话中文会出现乱码(英文正常),这就导致用Jmail组件收发邮件时有些邮箱的正常,有些邮箱乱码,不够完善。


例如:


QQ邮箱:


  Subject: =?gbk?B?1rG907T4uL28/reiy80=?=


U-Mail邮箱


   Subject: =?utf-8?B?5oiR5b6X57uZ5oiR?=



正是因为前几天帮同学弄Jmail收邮件的时候碰到此类问题,所以从网上收集了一些这方面的一些资源,希望能让大家少走点弯路!



Jmail的subject共分3段,=?和?=是结束和结尾标记
第一段:utf-8,原来页面的编码方式
第二段:B是指邮件的编码方式B就是base64
第三段:5oiR5b6X57uZ5oiR标题的内容,但是经过Base64编码了
所以出现了QQ邮箱收邮件正常,而收取U-Mail中的邮件时标题乱码的现象,本质就是U-mail用到的是UTF-8编码
看到了本质要解决Jmail收件标题乱码就很简单了。只要获取subject第3个问号和第4个问号间的内容进行base64解码即可。



VB部分:


Option Explicit
Dim i&, Attachment&
Dim att As Object
Dim EmailMsg As Object
Dim atts As Object
Dim JMail As Object
Dim EmailList$, Subject$, EmailID&
Dim X$()
Private Sub Command1_Click()
Dim J#
Set JMail = CreateObject("JMail.POP3")
JMail.Connect
"***@163.com", "***", "pop.163.com", "110" 'JMail.Connect "邮箱名", "密码", "服务器" [,"端口号"]
'
Debug.Print "你有" & JMail.Count & "封邮件" '邮件数量
For i = 1 To JMail.Count
' EmailID = JMail.GetMessageUID(I) '邮件唯一ID标识
Set EmailMsg = JMail.Messages.Item(i) '取得一条邮件信息
'
-----------------------------------------------------------------------------取得附件数量并下载
Set atts = EmailMsg.Attachments '附件集合
Attachment = atts.Count '附件的数量
If Attachment > 0 Then
For J = 0 To Attachment - 1
Set att = atts(J)
If Dir(App.Path & "\" & att.Name) = "" Then 'att.Name附件的名称,如果存在同名文件而不加判断则会出错
att.SaveToFile App.Path & "\" & att.Name
End If
Next J
End If
'------------------------------------------------------------------------------以下为各种参数设置
'
EmailMsg.Charset = "gb2312" '编码方式
'
EmailMsg.ContentTransferEncoding = "base64"'解码方式
'
EmailMsg.Encoding = "base64"
'
EmailMsg.ContentType = "multipart/mixed" '发送邮件时
'
EmailMsg.ContentType = "text/html" '接收邮件时
'
EmailMsg.ISOEncodeHeaders = False'True '功能不清?
'
-----------------------------------------------------------------------------可以取得的各元素
'
MsgBox EmailMsg.Priority '邮件的优先级,1-5,1最高,正常情况为3。
'
MsgBox EmailMsg.From '邮件的发送人的信箱地址
'
MsgBox EmailMsg.FromName '邮件的发送人
'
MsgBox EmailMsg.Date '邮件日期
'
MsgBox EmailMsg.Body '邮件内容
'
MsgBox EmailMsg.Size '邮件大小
'
----------------------------------------------------------------------------
Subject = EmailMsg.Headers.GetHeader("Subject") '邮件标题,可正常解码,但UTF-8格式的标题取不全
X = Split(EmailMsg.Headers.GetHeader("Subject"), "?")
If X(1) = "UTF-8" Then
Subject
= Utf8ToUnicode(StrToBytes(X(3)))
Else
Subject
= Base64Decode(X(3))
End If
' Subject = EmailMsg.Headers.GetHeader("From") '发件人,可解码
'
Subject = EmailMsg.Headers.GetHeader("FromName")
EmailList = EmailList & CStr(i) & "" & Subject & vbCrLf
DoEvents
Next
Text1.Text
= EmailList
End Sub


Base64.bas模块:


Option Explicit
Public Const cstBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
Public arrBase64() As String
Private Declare
Function MultiByteToWideChar Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpMultiByteStr As Long, ByVal cchMultiByte As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long) As Long
Private Declare Function WideCharToMultiByte Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long, ByVal lpMultiByteStr As Long, ByVal cchMultiByte As Long, ByVal lpDefaultChar As Long, ByVal lpUsedDefaultChar As Long) As Long
Private Const CP_ACP = 0 ' default to ANSI code page
Private Const CP_UTF8 = 65001 ' default to UTF-8 code page
Public Function Base64Encode(strSource As String) As String '编码
On Error Resume Next
If UBound(arrBase64) = -1 Then
arrBase64
= Split(StrConv(cstBase64, vbUnicode), vbNullChar)
End If
Dim arrB() As Byte, bTmp(2) As Byte, bT As Byte
Dim i As Long, J As Long
arrB
= StrConv(strSource, vbFromUnicode)

J
= UBound(arrB)
For i = 0 To J Step 3
Erase bTmp
bTmp(
0) = arrB(i + 0)
bTmp(
1) = arrB(i + 1)
bTmp(
2) = arrB(i + 2)

bT
= (bTmp(0) And 252) / 4
Base64Encode
= Base64Encode & arrBase64(bT)

bT
= (bTmp(0) And 3) * 16
bT
= bT + bTmp(1) \ 16
Base64Encode
= Base64Encode & arrBase64(bT)

bT
= (bTmp(1) And 15) * 4
bT
= bT + bTmp(2) \ 64
If i + 1 <= J Then
Base64Encode
= Base64Encode & arrBase64(bT)
Else
Base64Encode
= Base64Encode & "="
End If

bT
= bTmp(2) And 63
If i + 2 <= J Then
Base64Encode
= Base64Encode & arrBase64(bT)
Else
Base64Encode
= Base64Encode & "="
End If
Next
End Function
Public Function Base64Decode(strEncoded As String) As String '解码
On Error Resume Next
Dim arrB() As Byte, bTmp(3) As Byte, bT As Long, bRet() As Byte
Dim i As Long, J As Long
arrB
= StrConv(strEncoded, vbFromUnicode)
J
= InStr(strEncoded & "=", "=") - 2
ReDim bRet(J - J \ 4 - 1)
For i = 0 To J Step 4
Erase bTmp
bTmp(
0) = (InStr(cstBase64, Chr(arrB(i))) - 1) And 63
bTmp(
1) = (InStr(cstBase64, Chr(arrB(i + 1))) - 1) And 63
bTmp(
2) = (InStr(cstBase64, Chr(arrB(i + 2))) - 1) And 63
bTmp(
3) = (InStr(cstBase64, Chr(arrB(i + 3))) - 1) And 63
bT
= bTmp(0) * 2 ^ 18 + bTmp(1) * 2 ^ 12 + bTmp(2) * 2 ^ 6 + bTmp(3)
bRet((i
\ 4) * 3) = bT \ 65536
bRet((i
\ 4) * 3 + 1) = (bT And 65280) \ 256
bRet((i
\ 4) * 3 + 2) = bT And 255
Next
Base64Decode
= StrConv(bRet, vbUnicode)
End Function

Function StrToBytes(ByVal Source As String) As Byte()
Dim bB64Str() As Byte
bB64Str
= StrConv(Source, vbFromUnicode)
Dim lB64Len As Long
lB64Len
= InStrB(bB64Str, ChrB$(Asc("="))) - 1
Dim lLenPad As Long
lLenPad
= (4 - lB64Len Mod 4) Mod 4
Dim lLen As Long
lLen
= ((lB64Len + lLenPad) \ 4) * 3
Dim bStr() As Byte
ReDim bStr(lLen - 1)
lLen
= lLen - lLenPad
Dim i As Long
Dim lBuffer As Long
For i = 0 To lB64Len - 1 Step 4
lBuffer
= DeB64CodeA(bB64Str(i + 0)) * &H40000 Or DeB64CodeA(bB64Str(i + 1)) * &H1000& _
Or DeB64CodeA(bB64Str(i + 2)) * &H40& Or DeB64CodeA(bB64Str(i + 3))
bStr((i
\ 4) * 3 + 2) = lBuffer And &HFF&
lBuffer
= lBuffer \ &H100&
bStr((i
\ 4) * 3 + 1) = lBuffer And &HFF&
lBuffer
= lBuffer \ &H100&
bStr((i
\ 4) * 3 + 0) = lBuffer And &HFF&
lBuffer
= lBuffer \ &H100&
Next
ReDim Preserve bStr(lLen - 1)
StrToBytes
= bStr
End Function
Private Function DeB64CodeA(ByVal Char As Byte) As Byte
Select Case Char
Case Asc("A") To Asc("Z"): DeB64CodeA = Char - Asc("A")
Case Asc("a") To Asc("z"): DeB64CodeA = Char - Asc("a") + 26
Case Asc("0") To Asc("9"): DeB64CodeA = Char - Asc("0") + 52
Case Asc("+"): DeB64CodeA = 62
Case Asc("/"): DeB64CodeA = 63
Case Asc("="): DeB64CodeA = 64
End Select
End Function
Function Utf8ToUnicode(ByRef Utf() As Byte) As String
Dim lRet As Long
Dim lLength As Long
Dim lBufferSize As Long
lLength
= UBound(Utf) - LBound(Utf) + 1
If lLength <= 0 Then Exit Function
lBufferSize
= lLength * 2
Utf8ToUnicode
= String$(lBufferSize, Chr(0))
lRet
= MultiByteToWideChar(CP_UTF8, 0, VarPtr(Utf(0)), lLength, StrPtr(Utf8ToUnicode), lBufferSize)
If lRet <> 0 Then
Utf8ToUnicode
= Left(Utf8ToUnicode, lRet)
End If
End Function


C#部分:


#region base64解码
public static string base64GbkDecode(string data)
{
string decode = "";
byte[] bytes = Convert.FromBase64String(data);
try
{
decode
= Encoding.GetEncoding("gb2312").GetString(bytes);
}
catch (Exception ex1)
{
//return "Error in base64Encode" + ex1.Message;
}
return decode;
}

public static string base64Utf8Decode(string data)
{
string result = "";
try
{
System.Text.UTF8Encoding encoder
= new System.Text.UTF8Encoding();
System.Text.Decoder utf8Decode
= encoder.GetDecoder();
byte[] todecode_byte = Convert.FromBase64String(data);
int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
char[] decoded_char = new char[charCount];
utf8Decode.GetChars(todecode_byte,
0, todecode_byte.Length, decoded_char, 0);
result
= new String(decoded_char);
}
catch (Exception e)
{
//return "Error in base64Encode" + e.Message;
}
return result;
}

//base64解码
public static string DecodeStr(string allstr, string code)
{
//形如=?...?=是结束开始的标志
//=?utf-8?B?5rWL6K+V5o6l5pS25pys6YKu5Lu26L+Z5piv5Li76aKY?=
//=?gbk?B?suLK1L3TytXN4rK/08q8/tXiuPbKx9b3zOU=?=
//返回的字符串
string str = "";
if (code == "gbk")
{
str
= base64GbkDecode(allstr);
}
else if (code == "utf-8")
{
str
= base64Utf8Decode(allstr);
}
return str;
}
#endregion


调用:


string subjectStr = popMail.Messages[i].Headers.GetHeader("Subject");
subjectstr
= DecodeStr(subjectallstr.Split('?')[3], “utf-8”);


注意:如果原来页面用的是UTF-8编码,一定要用popMail.Messages[i].Headers.GetHeader(“Subject”)的形式,popMail.Messages[i].Subject得到的将是直接经jmail解码后的乱码


该文章在 2011/12/22 12:30:55 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved