2016-10-06 49 views
7

Tôi có một ứng dụng mà sẽ gửi email có đính kèm hình ảnh qua một máy chủ SMTP (sendgrid)SMTP mail server (sendgrid) lỗi trên trình

Khi ứng dụng khởi chạy nó intitilaizes một kết nối Socket và xác thực người sử dụng (ứng dụng. Tôi thấy thông báo sau trở về từ Sendgrid

SG ESMTP service ready at<foo..sendgrid.net 

và tôi cũng có được một xác thực thành công trở lại.

Tuy nhiên trên gửi bất kỳ email tôi nhận được sau 3 lỗi

error 1 550 Unauthenticated senders not allowed 
error 2 503 Must have sender before recipient 
error 3 503 Must have valid receiver and originator 

Vì vậy, điều này gợi ý với tôi rằng tôi phải thay đổi thứ tự của người gửi và người nhận trong mô-đun SMTP của tôi. Trong nội bộ tôi đang dùng một ByteArray đến và chuyển đổi thành chuỗi base64 để gửi email với các tập tin đính kèm.

Vậy làm cách nào để thay đổi đoạn mã sau?

 writeUTFBytes ("MAIL FROM: <"+pFrom+">\r\n"); 
     writeUTFBytes ("RCPT TO: <"+pDest+">\r\n"); 
     writeUTFBytes ("DATA\r\n"); 
     writeUTFBytes ("From: "+pFrom+"\r\n"); 
     writeUTFBytes ("To: "+pDest+"\r\n"); 

Đây là toàn bộ lớp tôi đang sử dụng. Tôi gọi xác thực chỉ một lần sau khi lớp được khởi tạo và sau đó sendAttachedMail khi gửi email kèm theo tệp đính kèm hình ảnh. Và khi thử nghiệm sử dụng máy chủ SMTP cục bộ KHÔNG xác thực, mọi thứ hoạt động tốt (email và file đính kèm hình ảnh gửi)

package org.bytearray.smtp.mailer 
{ 
    import flash.events.ProgressEvent; 
    import flash.net.Socket; 
    import flash.utils.ByteArray; 
    import flash.utils.getTimer; 

    import org.bytearray.smtp.crypto.MD5; 
    import org.bytearray.smtp.encoding.Base64; 
    import org.bytearray.smtp.events.SMTPEvent; 
    import org.bytearray.smtp.infos.SMTPInfos; 

    public class SMTPMailer extends Socket 
    { 
     private var sHost:String; 
     private var buffer:Array = new Array(); 

     // regexp pattern 
     private var reg:RegExp = /^\d{3}/img; 

     // PNG, JPEG header values 
     private static const PNG:Number = 0x89504E47; 
     private static const JPEG:Number = 0xFFD8; 

     // common SMTP server response codes 
     // other codes could be added to add fonctionalities and more events 
     private static const ACTION_OK:Number = 0xFA; 
     private static const AUTHENTICATED:Number = 0xEB; 
     private static const DISCONNECTED:Number = 0xDD; 
     private static const READY:Number = 0xDC; 
     private static const DATA:Number = 0x162; 
     private static const BAD_SEQUENCE:Number = 0x1F7; 

     public function SMTPMailer (pHost:String, pPort:int) 
     { 
      super (pHost, pPort);   
      sHost = pHost; 
      addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler,false,0,true); 
     } 

     public function reset():void{ 
      removeEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler); 
     } 

     /* 
     * This method lets you authenticate, just pass a login and password 
     */ 
     public function authenticate (pLogin:String, pPass:String):void 
     { 
      writeUTFBytes ("EHLO "+sHost+"\r\n"); 
      writeUTFBytes ("AUTH LOGIN\r\n"); 
      writeUTFBytes (Base64.encode64String (pLogin)+"\r\n"); 
      writeUTFBytes (Base64.encode64String (pPass)+"\r\n"); 
      flush(); 
     } 

     /* 
     * This method is used to send emails with attached files and HTML 
     * takes an incoming Bytearray and convert it to base64 string 
     * for instance pass a JPEG ByteArray stream to get a picture attached in the mail ;) 
     */ 
     public function sendAttachedMail (pFrom:String, pDest:String, pSubject:String, pMess:String, pByteArray:ByteArray, pFileName:String) :void 
     { 
      try { 

       writeUTFBytes ("HELO "+sHost+"\r\n"); 
       writeUTFBytes ("MAIL FROM: <"+pFrom+">\r\n"); 
       writeUTFBytes ("RCPT TO: <"+pDest+">\r\n"); 
       writeUTFBytes ("DATA\r\n"); 
       writeUTFBytes ("From: "+pFrom+"\r\n"); 
       writeUTFBytes ("To: "+pDest+"\r\n"); 
       writeUTFBytes ("Date : "+new Date().toString()+"\r\n"); 
       writeUTFBytes ("Subject: "+pSubject+"\r\n"); 
       writeUTFBytes ("Mime-Version: 1.0\r\n"); 

       var md5Boundary:String = MD5.hash (String (getTimer())); 

       writeUTFBytes ("Content-Type: multipart/mixed; boundary=------------"+md5Boundary+"\r\n"); 
       writeUTFBytes("\r\n"); 
       writeUTFBytes ("This is a multi-part message in MIME format.\r\n"); 
       writeUTFBytes ("--------------"+md5Boundary+"\r\n"); 
       writeUTFBytes ("Content-Type: text/html; charset=UTF-8; format=flowed\r\n"); 
       writeUTFBytes("\r\n"); 
       writeUTFBytes (pMess+"\r\n"); 
       writeUTFBytes ("--------------"+md5Boundary+"\r\n"); 
       writeUTFBytes (readHeader (pByteArray, pFileName)); 
       writeUTFBytes ("Content-Transfer-Encoding: base64\r\n"); 
       writeUTFBytes ("\r\n"); 

       var base64String:String = Base64.encode64 (pByteArray, true); 

       writeUTFBytes (base64String+"\r\n"); 
       writeUTFBytes ("--------------"+md5Boundary+"-\r\n"); 
       writeUTFBytes (".\r\n"); 
       flush(); 

      } catch (pError:Error) 
      { 
       trace("Error : Socket error, please check the sendAttachedMail() method parameters"); 
       trace("Arguments : " + arguments);  
      } 
     } 

     /* 
     * This method is used to send HTML emails 
     * just pass the HTML string to pMess 
     */ 
     public function sendHTMLMail (pFrom:String, pDest:String, pSubject:String, pMess:String):void 
     { 
      try 
      {   
       writeUTFBytes ("HELO "+sHost+"\r\n"); 
       writeUTFBytes ("MAIL FROM: <"+pFrom+">\r\n"); 
       writeUTFBytes ("RCPT TO: <"+pDest+">\r\n"); 
       writeUTFBytes ("DATA\r\n"); 
       writeUTFBytes ("From: "+pFrom+"\r\n"); 
       writeUTFBytes ("To: "+pDest+"\r\n"); 
       writeUTFBytes ("Subject: "+pSubject+"\r\n"); 
       writeUTFBytes ("Mime-Version: 1.0\r\n"); 
       writeUTFBytes ("Content-Type: text/html; charset=UTF-8; format=flowed\r\n"); 
       writeUTFBytes("\r\n"); 
       writeUTFBytes (pMess+"\r\n"); 
       writeUTFBytes (".\r\n"); 
       flush(); 

      } catch (pError:Error) 
      { 
       trace("Error : Socket error, please check the sendHTMLMail() method parameters"); 
       trace("Arguments : " + arguments); 
      } 
     } 

     /* 
     * This method automatically detects the header of the binary stream and returns appropriate headers (jpg, png) 
     * classic application/octet-stream content type is added for different kind of files 
     */ 
     private function readHeader (pByteArray:ByteArray, pFileName:String):String 
     { 
      pByteArray.position = 0; 

      var sOutput:String = null; 

      if (pByteArray.readUnsignedInt() == SMTPMailer.PNG) 
      { 
       sOutput = "Content-Type: image/png; name="+pFileName+"\r\n"; 
       sOutput += "Content-Disposition: attachment filename="+pFileName+"\r\n"; 
       return sOutput; 
      } 

      pByteArray.position = 0; 

      if (pByteArray.readUnsignedShort() == SMTPMailer.JPEG) 
      { 
       sOutput = "Content-Type: image/jpeg; name="+pFileName+"\r\n"; 
       sOutput += "Content-Disposition: attachment filename="+pFileName+"\r\n"; 
       return sOutput; 
      } 

      sOutput = "Content-Type: application/octet-stream; name="+pFileName+"\r\n"; 
      sOutput += "Content-Disposition: attachment filename="+pFileName+"\r\n"; 

      return sOutput; 
     } 

     // check SMTP response and dispatch proper events 
     // Keep in mind SMTP servers can have different result messages the detection can be modified to match some specific SMTP servers 
     private function socketDataHandler (pEvt:ProgressEvent):void 
     { 
      var response:String = pEvt.target.readUTFBytes (pEvt.target.bytesAvailable); 
      buffer.length = 0; 
      var result:Array = reg.exec(response); 

      while (result != null) 
      { 
       buffer.push (result[0]); 
       result = reg.exec(response); 
      } 

      var smtpReturn:Number = buffer[buffer.length-1]; 
      var smtpInfos:SMTPInfos = new SMTPInfos (smtpReturn, response); 

      if (smtpReturn == SMTPMailer.READY) 
       dispatchEvent (new SMTPEvent (SMTPEvent.CONNECTED, smtpInfos)); 

      else if (smtpReturn == SMTPMailer.ACTION_OK && (response.toLowerCase().indexOf ("queued") != -1 || response.toLowerCase().indexOf ("accepted") != -1 || 
        response.toLowerCase().indexOf ("qp") != -1)) dispatchEvent (new SMTPEvent (SMTPEvent.MAIL_SENT, smtpInfos)); 
      else if (smtpReturn == SMTPMailer.AUTHENTICATED) 
       dispatchEvent (new SMTPEvent (SMTPEvent.AUTHENTICATED, smtpInfos)); 
      else if (smtpReturn == SMTPMailer.DISCONNECTED) 
       dispatchEvent (new SMTPEvent (SMTPEvent.DISCONNECTED, smtpInfos)); 
      else if (smtpReturn == SMTPMailer.BAD_SEQUENCE) 
       dispatchEvent (new SMTPEvent (SMTPEvent.BAD_SEQUENCE, smtpInfos)); 
      else if (smtpReturn != SMTPMailer.DATA) 
       dispatchEvent (new SMTPEvent (SMTPEvent.MAIL_ERROR, smtpInfos));  
     } 
    } 
} 
+0

Xin lưu ý rằng tôi đang sử dụng thư viện SMTP này ... http: //www.bytearray.org/? P = 27 https://code.google.com/archive/p/smtpmailer/downloads Nếu bạn có thể làm cho nó hoạt động với SendGrid và cung cấp câu trả lời tôi sẽ thưởng +500 –

Trả lời

0

So this suggests to me that I must change the order of sender and recipient in my SMTP module.

Trình tự các lệnh của bạn là đúng. Thay vào đó, bạn nên nhìn vào các thông báo lỗi đầu tiên cho nguyên nhân thực sự của vấn đề:

error 1 550 Unauthenticated senders not allowed 

này sẽ cho bạn biết rằng server requires authentication từ người gửi, ví dụ: sử dụng SMTP AUTH lệnh với thông tin người dùng. Nỗ lực gửi thư từ người gửi chưa được xác thực sẽ bị từ chối. Do đó, nếu MAIL FROM không thành công thì RCPT TO sẽ không thành công. Nếu RCPT TO không thành công, thì DATA không thành công. Và cứ thế.

Sử dụng lệnh SMTP EHLO để khám phá các sơ đồ AUTH (và các khả năng khác) mà máy chủ hỗ trợ, sau đó gửi lệnh AUTH thích hợp trước khi gửi MAIL FROM.

+0

vâng tôi biết nhưng khi ứng dụng của tôi khởi chạy, tôi có thể thấy xác thực thành công. Nó là một kết nối socket XML. Vì có một người dùng (ứng dụng) duy nhất để xác thực nên tôi phải xác thực lại mỗi khi tôi gửi email? Giả định của tôi là thông báo lỗi đầu tiên có liên quan trực tiếp đến lỗi thứ 2 & thứ 3, tức là nếu tôi thay đổi người nhận, lệnh người gửi sai lỗi chính xác1 sẽ biến mất. –

+0

@eco_bach: Xác thực SMTP được thực hiện cho mỗi kết nối SMTP (tức là kết nối TCP). Từ mã bạn hiển thị, tôi không thể thấy bất kỳ xác thực nào cả. Và tôi cũng không biết ý bạn là gì với "ổ cắm XML", SMTP yêu cầu một ổ cắm TCP. Có thể bạn sẽ hiển thị thêm một số mã, đặc biệt là kết nối ban đầu với máy chủ SMTP và cách bạn xác thực thành công đối với máy chủ SMTP. –

+0

Sử dụng thư viện này http://www.bytearray.org/?p=27 https://code.google.com/archive/p/smtpmailer/downloads Chỉnh sửa bài đăng đầu tiên của tôi –

0

CẬP NHẬT: xin lỗi, tôi chưa xem xét kỹ lớp học của bạn. Bạn đã có một phương pháp xác thực và nó làm những gì nó cần. Vì vậy, rõ ràng, trong khi bạn nghĩ rằng bạn đang gọi nó, hoặc nó không phải là nhận được gọi là, hoặc nó không thành công.

Vì vậy, kiểm tra cẩn thận rằng kết nối bạn đang chứng thực trongkết nối bạn đang gửi mail trong thực sự cùng một kết nối, và bạn không thể vô tình lại tạo ra một kết nối không được thẩm định mới .

Ngoài ra, bạn thực sự cần kiểm tra kết quả của các thao tác bạn thực hiện - trong trường hợp này là xác thực. Nó thực sự thành công?

Cũ câu trả lời

Từ ví dụ của bạn và những gì tài liệu nhỏ, tôi tìm thấy, bạn cần - hoặc ít nhất là xuất hiện cần - hai xác thực. Có lẽ là with the same username and password.

Việc đầu tiên bạn đang làm đúng, đó là 'kết nối socket XML' sẽ đưa bạn đến lớp SMTP.

Bây giờ bạn cần xác thực thứ hai. Nếu không, tất cả các lệnh sẽ thất bại và các lỗi sẽ tạo thành một cái khác, trong khi lỗi "thực", như Steffen Ulrich nhận thấy, là cái đầu tiên.

writeUTFBytes ("HELO "+sHost+"\r\n"); 

// Inner authentication 
writeUTFBytes ("AUTH LOGIN\r\n"); 
writeUTFBytes (Base64.encode64 (username) + "\r\n"); 
writeUTFBytes (Base64.encode64 (password) + "\r\n"); 
// HERE you really should read the stream and ensure it says 
// "Authentication OK" -- or something to that effect. 

writeUTFBytes ("MAIL FROM: <"+pFrom+">\r\n"); 
Các vấn đề liên quan