2016-02-26 79 views
2

我試圖在使用C#的Winforms應用程序中生成Gmail草稿消息。草稿消息需要採用HTML格式並能夠包含附件。帶MimeKit,C#Winforms和Google API的Gmail草案(帶附件的HTML)

我能夠使用AE.Net.Mail生成帶附件的草稿,但草稿消息是純文本格式的(我無法弄清楚如何編寫AE.Net.Mail來爲我提供HTML Gmail草稿消息)。

爲了將消息轉換爲HTML格式,我使用MimeKit取消System.Net.Mail消息並將其轉換爲MimeMessage消息。但是,我無法弄清楚如何根據Gmail草案規範的要求,以RFC 2822格式和URL安全的base64編碼字符串獲取MIME郵件。

下面是從MimeKit轉換嘗試的代碼:

var service = new GmailService(new BaseClientService.Initializer() 
{ 
    HttpClientInitializer = credential, 
    ApplicationName = ApplicationName, 
}); 

MailMessage msg = new MailMessage(); //System.Net.Mail 
msg.IsBodyHtml = true; 
msg.Subject = "HTML Email"; 
msg.Body = "<a href = 'http://www.yahoo.com/'>Enjoy Yahoo!</a>"; 
msg.Attachments.Add(file); 

MimeMessage message = MimeMessage.CreateFromMailMessage(msg); //MimeKit conversion 

//At this point I cannot figure out how to get the MIME message into 
//an RFC 2822 formatted and URL-safe base64 encoded string 
//as required by the Gmail draft specification 
//See working code below for how this works in AE.Net.Mail 

下面是使用AE.Net.Mail,工程的代碼,但生成的Gmail草案的正文作爲純文本(通過基於this article傑森Pettys):

var service = new GmailService(new BaseClientService.Initializer() 
{ 
    HttpClientInitializer = credential, 
    ApplicationName = ApplicationName, 
}); 

var msg = new AE.Net.Mail.MailMessage //msg created in plain text not HTML format 
{ 
    Body = "<a href = 'http://www.yahoo.com/'>Enjoy Yahoo!</a>" 
}; 

var bytes = System.IO.File.ReadAllBytes(filePath); 
AE.Net.Mail.Attachment file = new AE.Net.Mail.Attachment(bytes, @"application/pdf", FileName, true); 
msg.Attachments.Add(file); 

var msgStr = new StringWriter(); 
msg.Save(msgStr); 
Message m = new Message(); 
m.Raw = Base64UrlEncode(msgStr.ToString()); 

Draft draft = new Draft(); //Gmail draft 
draft.Message = m; 

service.Users.Drafts.Create(draft, "me").Execute(); 

private static string Base64UrlEncode(string input) 
{ 
    var inputBytes = System.Text.Encoding.ASCII.GetBytes(input); 
    // Special "url-safe" base64 encode. 
    return Convert.ToBase64String(inputBytes) 
     .Replace('+', '-') 
     .Replace('/', '_') 
     .Replace("=", ""); 
} 

有沒有辦法來MimeKit的MimeMessage消息轉換成格式化的RFC 2822和URL - 安全的base64編碼的字符串,以便它可以生成爲Gmail草稿?否則,有沒有辦法在編碼之前創建HTML格式的AE.Net.Mail消息?所有的幫助非常感謝。

+0

您有幾篇關於Drafts API Gmail的文章。您是否嘗試過使用EML格式下載草稿或消息? – Kiquenet

+0

@Kiquenet你在這個問題的下一個評論中提出了一個問題,我在答覆評論中回答,然後兩個都被刪除了。 (也許由你?)現在你在評論中發佈上述問題。我在這篇文章中的問題是在一年多前解決的。我不知道你爲什麼要詢問我是否嘗試過EML格式。我的問題已得到解答。我確實發佈了三個不同的問題。兩個人被回答,一個人保持開放狀態(我應該關閉,並且會把我的工作列入清單)。感謝您的關注,但我不再需要有關此特定問題的幫助。 – joeschwa

回答

2

做的最簡單的方法你想要的東西是這樣的:

static string Base64UrlEncode (MimeMessage message) 
{ 
    using (var stream = new MemoryStream()) { 
     message.WriteTo (stream); 

     return Convert.ToBase64String (stream.GetBuffer(), 0, (int) stream.Length) 
      .Replace ('+', '-') 
      .Replace ('/', '_') 
      .Replace ("=", ""); 
    } 
} 

,但這樣做的更有效的方式將需要實現我們自己的UrlEncoderFilter,以取代「.Replace(......)」邏輯:

using MimeKit; 
using MimeKit.IO; 
using MimeKit.IO.Filters; 

// ... 

class UrlEncodeFilter : IMimeFilter 
{ 
    byte[] output = new byte[8192]; 

    #region IMimeFilter implementation 
    public byte[] Filter (byte[] input, int startIndex, int length, out int outputIndex, out int outputLength) 
    { 
     if (output.Length < input.Length) 
      Array.Resize (ref output, input.Length); 

     int endIndex = startIndex + length; 

     outputLength = 0; 
     outputIndex = 0; 

     for (int index = startIndex; index < endIndex; index++) { 
      switch ((char) input[index]) { 
      case '\r': case '\n': case '=': break; 
      case '+': output[outputLength++] = (byte) '-'; break; 
      case '/': output[outputLength++] = (byte) '_'; break; 
      default: output[outputLength++] = input[index]; break; 
      } 
     } 

     return output; 
    } 

    public byte[] Flush (byte[] input, int startIndex, int length, out int outputIndex, out int outputLength) 
    { 
     return Filter (input, startIndex, length, out outputIndex, out outputLength); 
    } 

    public void Reset() 
    { 
    } 
    #endregion 
} 

而且你會使用這種方式是這樣的:

static string Base64UrlEncode (MimeMessage message) 
{ 
    using (var stream = new MemoryStream()) { 
     using (var filtered = new FilteredStream (stream)) { 
      filtered.Add (EncoderFilter.Create (ContentEncoding.Base64)); 
      filtered.Add (new UrlEncodeFilter()); 

      message.WriteTo (filtered); 
      filtered.Flush(); 
     } 

     return Encoding.ASCII.GetString (stream.GetBuffer(), 0, (int) stream.Length); 
    } 
} 
+0

謝謝!傳遞'MimeMessage'並將其寫入流是非常有意義的。我最終使用了我的「替換」邏輯,因爲我無法使UrlEncoderFilter工作。我試圖在電子郵件正文中放置的所有HTML都沒有正確編碼,並且被放在了一些gobbledygook中。如果時間允許,我會繼續努力,看看能否找出我出錯的地方。非常感謝您的幫助,並感謝您創建MimeKit! – joeschwa

0

失敗的是,有沒有辦法在編碼之前以HTML格式創建AE.Net.Mail消息?

您可以嘗試

msg.ContentType = "text/html"; 

在AE.Net.Mail.MailMessage

1

這裏是我用來創建帶有附件的Gmail草案的C#代碼...

using System; 
using Google.Apis.Auth.OAuth2; 
using Google.Apis.Gmail.v1; 
using Google.Apis.Services; 
using Google.Apis.Util.Store; 
using System.IO; 
using System.Threading; 
using System.Net.Mail; 

namespace SendStatusReportsAddin1 
{ 
    class Program 
    { 
     // If modifying these scopes, delete your previously saved credentials 
     // at ~/.credentials/gmail-dotnet-quickstart.json 
     //static string[] Scopes = { GmailService.Scope.GmailReadonly }; 
     static string[] Scopes = { GmailService.Scope.MailGoogleCom }; 
     static string ApplicationName = "Gmail API .NET Quickstart"; 

     static void Main(string[] args) 
     { 
      //Authorization 
       UserCredential credential; 

       using (var stream = 
        new FileStream("client_secret2.json", FileMode.Open, FileAccess.Read)) 
       { 
        string credPath = System.Environment.GetFolderPath(
         System.Environment.SpecialFolder.Personal); 
        credPath = Path.Combine(credPath, ".credentials3/gmail-dotnet.json"); 

        credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
         GoogleClientSecrets.Load(stream).Secrets, 
         Scopes, 
         "user", 
         CancellationToken.None, 
         new FileDataStore(credPath, true)).Result; 
        Console.WriteLine("Credential file saved to: " + credPath); 
       } 

      //Create Gmail API service. 
       var service = new GmailService(new BaseClientService.Initializer() 
       { 
        HttpClientInitializer = credential, 
        ApplicationName = ApplicationName, 
       }); 

      //Create mail message 
       MailMessage mailmsg = new MailMessage(); 
       { 
        mailmsg.Subject = "My test subject"; 
        mailmsg.Body = "<b>My smart message </b>"; 
        mailmsg.From = new MailAddress("[email protected]"); 
        mailmsg.To.Add(new MailAddress("[email protected]")); 
        mailmsg.IsBodyHtml = true; 
       } 

      //add attachment 
       string statusreportfile = 
         @"C:\Users\ey96a\Google Drive\10 Status-Vacation-Expense\Status Reports\UUM RewriteStatus Report.pdf"; 

       Attachment data = new Attachment(statusreportfile); 
       mailmsg.Attachments.Add(data); 

      //Make mail message a Mime message 
       MimeKit.MimeMessage mimemessage = MimeKit.MimeMessage.CreateFromMailMessage(mailmsg); 

      //Use Base64URLEncode to encode the Mime message 
       Google.Apis.Gmail.v1.Data.Message finalmessage = new Google.Apis.Gmail.v1.Data.Message(); 
       finalmessage.Raw = Base64UrlEncode(mimemessage.ToString()); 

      //Create the draft email 
       var mydraft = new Google.Apis.Gmail.v1.Data.Draft(); 
       mydraft.Message = finalmessage; 

       var resultdraft = service.Users.Drafts.Create(mydraft, "me").Execute(); 

      //Send the email (instead of creating a draft) 
       var resultsend = service.Users.Messages.Send(finalmessage, "me").Execute(); 

      //Open the SendStatusReports form 
       aOpenForm.myForm1(); 

     } //end of Main 

     //Base64 URL encode 
     public static string Base64UrlEncode(string input) 
     { 
      var inputBytes = System.Text.Encoding.UTF8.GetBytes(input); 
      // Special "url-safe" base64 encode. 

      return System.Convert.ToBase64String(inputBytes) 
       .Replace('+', '-') 
       .Replace('/', '_') 
       .Replace("=", ""); 
     } 

    } //end of class Program 

} 
+0

如何找到***草稿***併發送它? –