2015-01-24 4 views
7

Korzystanie z interfejsu API Gmaila w .Net. Tworzenie wiadomości za pomocą Net.Mail.MailMessage. Następnie za pomocą MimeKit utwórz MimeMessage (używając tego do wysyłania załącznika + wiadomości HTML). Przekazywanie MimeMessage.ToString do kodera Base64. Brak błędu interfejsu API. Kod przebiega przez ok. Widzę komunikat na stronie wysłanej w GMailu. Poczta wygląda perfekcyjnie (a wysłany identyfikator rzeczywiście zwraca wiadomość). Ale jest też następująca dołączona wiadomość do tej poczty w Gmailu.Wiadomości e-mail GMail API Bouncing

Bounce <[email protected]> 

An error occurred. Your message was not sent. 

Jak zwykle brak innych informacji od Google. Jak to naprawić?

 Dim msg = New Net.Mail.MailMessage 
     msg.Subject = subject 
     msg.To.Add(New MailAddress(ToEmail)) 
     msg.From = New MailAddress(FromEmail, SenderName) 
     msg.ReplyTo = New MailAddress(FromEmail, SenderName) 
     msg.Body = bodyText 
     msg.IsBodyHtml = True 

     If Not String.IsNullOrWhiteSpace(fileAttachment) Then 
      If System.IO.File.Exists(fileAttachment) Then 
       Dim Attachment As New Net.Mail.Attachment(fileAttachment, "application/pdf") 
       msg.Attachments.Add(Attachment) 
      End If 
     End If 
     Dim message As MimeMessage = MimeMessage.CreateFromMailMessage(msg) 
     Dim newMsg = New Google.Apis.Gmail.v1.Data.Message() 
     newMsg.Raw = Base64UrlEncode(message.ToString) 
     GmailService.Users.Messages.Send(newMsg, "me").Execute() 



Private Function Base64UrlEncode(ByVal input As String) As String 
      Dim inputBytes = System.Text.Encoding.UTF8.GetBytes(input) 
      'Special "url-safe" base64 encode. 
      Return Convert.ToBase64String(inputBytes).Replace("+", "-").Replace("/", "_").Replace("=", "") 
     End Function 

To jest wiadomość zwrotna. Jak widać wszystko wygląda dobrze. Praca z Google API jest najbardziej frustrująca.

200 OK 

- Hide headers - 

cache-control: no-cache, no-store, max-age=0, must-revalidate 
content-encoding: gzip 
content-length: 85 
content-type: application/json; charset=UTF-8 
date: Sat, 24 Jan 2015 05:57:21 GMT 
etag: "96Z6JVARoyR8skov3RseF4DCFpA/mFWFskkdSFxyjIhRJHJuhDCBvfY" 
expires: Fri, 01 Jan 1990 00:00:00 GMT 
pragma: no-cache 
server: GSE 
vary: Origin, X-Origin 

{ 
"id": "14b1a841e4fff910", 
"threadId": "14b1a841e4fff910", 
"labelIds": [ 
    "SENT" 
] 
} 
+0

postarać się o to uruchomiony w [API Explorer] (https://developers.google.com/gmail/api/v1/reference/users/messages/send#try-it) po pierwsze, patrz również http://stackoverflow.com/a/24461102/1545993 – Taifun

+0

Takie same wyniki w Eksploratorze API. Wiadomość przechodzi, ale nie została dostarczona. Tak, czytam tę stronę. Robię dokładnie to. Mój problem polega na tym, że jeśli coś jest nie tak w formacie, GMail API powinien mieć wyjątek. Ponadto poczta wygląda idealnie, gdy sprawdzę folder wysyłany w Gmailu. Oznacza to, że struktura danych i formatowanie były w porządku. Czy istnieje sposób na nawiązanie kontaktu z tymi świetnymi programistami Google? –

+0

Użyj przykładowego komunikatu, zakoduj go w base64 i sprawdź, czy uzyskasz taki sam wynik, najpierw uruchom go za pomocą eksploratora interfejsu API ... – Taifun

Odpowiedz

4

To jest szalone. To był problem.

Linia ta

msg.ReplyTo = New MailAddress(FromEmail, SenderName) 

niezależnie od powodów (myślę, gdy FromEmail i replyto są same e-maile) opuszcza dokument RFC2822 Reply-To parametru puste. Parametr pozostaje pusty nawet po skomentowaniu msg.ReplyTo. Nie trzeba dodawać, że GMail API wydaje się mieć problemy z pozostawieniem pustego pola Reply-To. Z całą pewnością błąd programowania.

Więc musiałem zrobić to hack w ostatecznej wiadomości RFC2882.

inputTxt = Replace(inputTxt, "Reply-To:", "Reply-To: " & FromEmail) 

Działa teraz.

********* jak wskazano w komentarzu poniżej, można użyć MailMessage.ReplyToList.Add(), aby rozwiązać ten problem. Problem polega na tym, że w interfejsie API Gmaila wymagany jest adres ReplyTo (nawet jeśli można założyć, że domyślnie ReplyTo na e-mail From). **********

+1

Tak, puste jest pytanie "Odpowiedz do". Ale powodem, dla którego nie jest on dostępny dla zakodowanych kodowanych base64, jest użycie przestarzałego 'MailMessage.ReplyTo'. Jeśli zamiast tego użyjesz 'MailMessage.ReplyToList.Add()', wszystko działa poprawnie. – jansokoly

+0

@jansokoly Tak, masz rację –

2

Na wypadek, gdyby ktoś potknął się o to i chciał uzyskać odpowiedź w języku C#, oto, co udało mi się uzyskać przy użyciu poprzedniej odpowiedzi jako wskazówki, z MimeKit.

public void SendEmail(MyInternalSystemEmailMessage email) 
{ 
    var mailMessage = new System.Net.Mail.MailMessage(); 
    mailMessage.From = new System.Net.Mail.MailAddress(email.FromAddress); 
    mailMessage.To.Add(email.ToRecipients); 
    mailMessage.ReplyToList.Add(email.FromAddress); 
    mailMessage.Subject = email.Subject; 
    mailMessage.Body = email.Body; 
    mailMessage.IsBodyHtml = email.IsHtml; 

    foreach (System.Net.Mail.Attachment attachment in email.Attachments) 
    { 
     mailMessage.Attachments.Add(attachment); 
    } 

    var mimeMessage = MimeKit.MimeMessage.CreateFromMailMessage(mailMessage); 

    var gmailMessage = new Google.Apis.Gmail.v1.Data.Message { 
     Raw = Encode(mimeMessage.ToString()) 
    }; 

    Google.Apis.Gmail.v1.UsersResource.MessagesResource.SendRequest request = service.Users.Messages.Send(gmailMessage, ServiceEmail); 

    request.Execute(); 
} 

public static string Encode(string text) 
{ 
    byte[] bytes = System.Text.Encoding.UTF8.GetBytes(text); 

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