代码之家  ›  专栏  ›  技术社区  ›  Shane Brodie

生成的电子邮件中出现奇怪的字符

  •  0
  • Shane Brodie  · 技术社区  · 7 月前

    使用GMail api从各种应用程序中发送电子邮件。使用MimeKit生成消息内容。问题是,当我生成消息并发送时,输出中总是会出现许多字符实例。这些字符都出现在电子邮件的签名块中,位于电话号码之前。

    我写了一个示例应用程序。Net Core控制台应用程序,演示了问题:

    using Google.Apis.Auth.OAuth2;
    using Google.Apis.Gmail.v1;
    using Google.Apis.Gmail.v1.Data;
    using Google.Apis.Services;
    using Google.Apis.Util.Store;
    using MimeKit;
    using System.Text;
    
    
    string[] Scopes = {"https://www.googleapis.com/auth/userinfo.email",
            "https://www.googleapis.com/auth/gmail.send",
            "https://www.googleapis.com/auth/gmail.settings.basic"};
    string ApplicationName = "EMailIntegration";
    string mySignature = string.Empty;
    string myEMail = string.Empty;
    string template = "<!DOCTYPE html><html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /><style>body { font-family: Arial, sans-serif; color: #231F20;}</style></head><body>%body%<br>%signature%</body></html>";
    
    UserCredential credential = null;
    
    var success = await DoAuthenticationAsync();
    
    if (success == false)
    {
        Console.WriteLine("Authentication failed!");
        Console.ReadLine();
        return;
    }
    else
    {
        Console.WriteLine($"Authenticated as {myEMail}");
    }
    
    //call your gmail service
    var service = new GmailService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = ApplicationName });
    
    //create the Google message object
    var msg = new Google.Apis.Gmail.v1.Data.Message();
    
    string[] sendTo = { "[email protected]" };   
    
    MimeKit.MimeMessage mimeMsg = new MimeKit.MimeMessage();
    
    //add the message destinations
    foreach (string dest in sendTo)
    {
        mimeMsg.To.Add(MimeKit.MailboxAddress.Parse(dest));
    }
    
    var msgBlob = template.Replace("%body%", "<p>This is a test to see if we can eliminate issues with strange characters appearing in signature blocks.</p>");
    msgBlob = msgBlob.Replace("%signature%", mySignature);
    
    mimeMsg.Subject = "Email Integration Testing";
    
    mimeMsg.Body = new TextPart(MimeKit.Text.TextFormat.Html)
    {
        Text = msgBlob
    };
    
    msg.Raw = Base64UrlEncode(mimeMsg.ToString());
    
    //send the message
    service.Users.Messages.Send(msg, "me").Execute();
    
    Console.WriteLine($"Sent!");
    
    Console.ReadLine();
    
    string Base64UrlEncode(string input)
    {
        var data = Encoding.UTF8.GetBytes(input);
        return Convert.ToBase64String(data)
            .Replace("+", "-")
            .Replace("/", "_")
            .Replace("=", "");
    }
    
    //The following code is used to authenticate with Google API, obtain the users email address and signature block.
    async Task<bool> DoAuthenticationAsync()
    {
        ClientSecrets secrets;
    
        // this obtains the application secrets data we need to indicate our application is asking to authenticate.
        using (var strm = new FileStream("credentials.json", FileMode.Open, FileAccess.Read))
        {
            secrets = GoogleClientSecrets.FromStream(strm).Secrets;
        }
    
        try
        {
            // this is the magic black box that does the authenticating.
            credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(secrets, Scopes, "user", CancellationToken.None, new FileDataStore("Google.API.Auth", false));
    
            var init = new BaseClientService.Initializer();
            init.HttpClientInitializer = credential;
    
            var svc = new GmailService(init);
    
            // this grabs the list of all e-mail aliases for the signed-in user and selects the primary
            ListSendAsResponse result = svc.Users.Settings.SendAs.List("me").Execute();
    
            foreach (SendAs itm in result.SendAs)
            {
                if (itm.IsPrimary.HasValue)
                {
                    if (itm.IsPrimary == true)
                    {
                        // save as the signature blob to use.
                        mySignature = itm.Signature;
                        myEMail = itm.SendAsEmail;
                        break;
                    }
                }
            }
        }
        catch (Exception)
        {
            return false;
        }
    
        return true;
    }
    

    从谷歌提取的签名块看起来与此“相似”:

    <div dir="ltr">
        <table style="color:rgb(35,31,32);font-family:Arial,sans-serif;font-size:medium;width:554px">
            <tbody>
                <tr>
                    <td width="275px">
                        <div style="font-size:14pt;font-weight:bold">Shane Brodie</div>
                        <div style="font-family:Aral,sans-serif;font-size:10pt;margin-bottom:10px">Senior Programmer/Analyst</div>
                        <div style="font-size:10pt;margin-bottom:4px"><strong>Toll Free:</strong> 204-555-1234</div>
                        <div style="font-size:10pt;margin-bottom:4px"><strong>Office:</strong> 204-555-1234</div>
                        <div style="font-size:10pt;margin-bottom:4px"><b>Extension:</b> 123</div>
                        <div style="font-size:10pt;margin-bottom:4px"><b>Cell Phone:</b> 204-555-1234</div>
                        <div style="font-size:10pt;margin-bottom:4px"><a href="mailto:[email protected]" target="_blank">[email protected]</a></div>
                    </td>
                    <td style="width:4px;border-right:4px solid rgb(65,65,66);height:142px">
                    </td>
                    <td width="275px">
                        <div style="padding-bottom:5px"><a href="https://maverickind.ca/" target="_blank"><img src="http://maverickind.ca/wp-content/uploads/2023/11/maverick.png" width="200px" style="margin-bottom:10px;font-style:italic"></a></div>
                        <div style="display:table">
                            <div style="display:table-row">
                                <div style="display:table-cell"><a href="http://www.intersteel.ca/" title="Intersteel" target="_blank"><img src="http://maverickind.ca/wp-content/uploads/2023/12/INT-Sig-e1707227175846.png" style="width:40.5px;height:40.5px"></a></div>
                                <div style="display:table-cell"><a href="https://defenderpumpguard.com/" title="Defender" target="_blank"><img src="http://maverickind.ca/wp-content/uploads/2023/12/Def-Fist-Sig-e1707227150848.png" style="width:40.5px;height:40.5px"></a></div>
                                <div style="display:table-cell"><a href="http://www.maverickind.ca/" title="Maverick Industries Ltd." target="_blank"><img src="http://maverickind.ca/wp-content/uploads/2023/12/Mav-Horns-SIG-e1707227104191.png" style="width:40.5px;height:40.5px"></a></div>
                            </div>
                        </div>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
    

    我对数据进行了轻微的清理,并对其进行了格式化,以便于查看。任何想法都将不胜感激。我已经为这个问题奋斗了好几个星期。

    1 回复  |  直到 7 月前
        1
  •  3
  •   jstedfast    7 月前

    不要使用MimeMessage。ToString()用于序列化消息。

    使用MimeMessage。改为WriteTo()。

    using (var memory = new MemoryStream ()) {
        var format = FormatOptions.Default.Clone ();
        format.NewLineFormat = NewLineFormat.Dos;
    
        mimeMsg.WriteTo (format, memory);
    
        var msgData = memory.ToArray ();
    
        msg.Raw = Base64UrlEncode (msgData);
    }
    
    string Base64UrlEncode(byte[] data)
    {
        return Convert.ToBase64String(data)
            .Replace("+", "-")
            .Replace("/", "_")
            .Replace("=", "");
    }