zoukankan      html  css  js  c++  java
  • Jmail接收邮件及UTF8解码问题(含VB及C#代码)

    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解码后的乱码

  • 相关阅读:
    Windows 7 远程协助
    Windows 7 帮助和支持资源—第三方网站
    Windows 7 帮助和支持资源—第三方软件
    数据结构-队列
    数据结构-栈
    pycharm每日技巧-2
    数据结构-链表
    时间处理-1
    二维数组的排序
    《疯狂的简洁》书摘
  • 原文地址:https://www.cnblogs.com/mic86/p/1970740.html
Copyright © 2011-2022 走看看