2016-02-26 1 views
2

Je tente de générer un brouillon Gmail dans une application WinForms en utilisant C#. Le brouillon de message doit être au format HTML et pouvoir contenir une pièce jointe.Brouillon Gmail (HTML avec pièce jointe) avec MimeKit, Winforms C# et API Google

J'ai été en mesure de générer un brouillon avec une pièce jointe en utilisant AE.Net.Mail, mais le brouillon du message était en texte brut (je ne pouvais pas comprendre comment coder AE.Net.Mail pour me donner un brouillon HTML Gmail). Pour tenter d'obtenir le message dans un format HTML, j'ai utilisé MimeKit pour prendre un message System.Net.Mail et le convertir en un message MimeMessage. Cependant, je n'arrive pas à comprendre comment envoyer le message MIME dans une chaîne codée en base64 formatée et sécurisée pour l'URL, conforme à la RFC 2822, comme l'exige le projet de spécification Gmail.

Voici le code de la MimeKit Conversion tentative:

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 

Voici le code à l'aide AE.Net.Mail qui fonctionne, mais génère le corps du projet de Gmail sous forme de texte (basé sur this article par Jason 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("=", ""); 
} 

Est-il possible de convertir un message de MimeKit MimeMessage dans une RFC 2822 formaté et URL -safe string encodé en base64 pour qu'il puisse être généré en tant que brouillon Gmail? A défaut, existe-t-il un moyen de créer un message AE.Net.Mail au format HTML avant de l'encoder? Toute aide est grandement appréciée.

+0

Vous avez plusieurs articles à propos de Brouillons API Gmail. avez-vous essayé de télécharger le brouillon ou le message au format EML? – Kiquenet

+0

@ Kiquenet vous avez posé une question dans un commentaire précédent ci-dessous cette question, j'ai répondu dans un commentaire de réponse, puis les deux ont été supprimés. (Peut-être par vous?) Maintenant, vous postez la question ci-dessus dans un commentaire. Ma question dans ce post a été résolue il y a plus d'un an. Je ne sais pas pourquoi vous posez d'autres questions pour savoir si j'ai essayé le format EML. Mes questions ont été répondues. J'ai posté trois questions différentes. Deux ont reçu une réponse et un reste ouvert (que je devrais fermer et mettra sur ma liste de choses à faire).Merci de votre intérêt, mais je n'ai plus besoin d'aide pour cette question spécifique. – joeschwa

Répondre

2

La façon la plus simple de faire ce que vous voulez est quelque chose comme ceci:

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 ("=", ""); 
    } 
} 

, mais d'une manière plus efficace de le faire, il faudrait mettre en œuvre notre propre UrlEncoderFilter pour remplacer votre « .Replacer (...) » logique:

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 
} 

Et la façon dont vous souhaitez utiliser est comme ceci:

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

Merci! Cela prend tout son sens de passer le 'MimeMessage' et de l'écrire dans un flux. J'ai fini par utiliser ma logique "replace" car je n'étais pas capable de faire fonctionner 'UrlEncoderFilter'. Tout le HTML que j'ai essayé de placer dans le corps de l'email ne s'est pas encodé correctement et a été placé comme des chaînes de gobbledygook. Si le temps le permet, je vais travailler sur ce point pour voir si je peux comprendre où je me trompe. Merci beaucoup pour votre aide et merci de créer MimeKit! – joeschwa

0

A défaut, existe-t-il un moyen de créer un message AE.Net.Mail au format HTML avant de l'encoder?

Vous pouvez

msg.ContentType = "text/html"; 

dans votre AE.Net.Mail.MailMessage

1

Voici le code C# je créer un projet de gmail avec une pièce jointe ...

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

Comment trouver *** projet *** et l'envoyer? –