最近用Sikuli做了個UI Test,要把結果用email的方式丟出來,找了一下,原本打算做模組化一點,各個不同的測試從Sikuli回傳給Python然後再去處理寄信的問題,後來討論了一下,多花力氣去維護一個語言不太划算(雖然我想玩Python啊),所以決定自己寫個頁面去做寄信的事。
找了一下,.NET有這個SmtpClient 類別可以來寄信,而且sample code也蠻詳細的,所以就來試一下了。
我是直接用需要帳號密碼登入才能用的gmail來寄,一開始的code是長這樣
其實這樣就可以寄了,但是拿不到成功或失敗的訊息,所以後來又加了SmtpClient.SendCompleted Event來去抓回應,這邊除了加上SendCompleted Event,寄信時原本是用.Send也要改成SendAsync,然後因為改成非同步模式,所以如果你在webpage上做的話,必須在 .aspx 的 <%@ Page %> 內加上 Async="true" ,不然會有錯誤訊息的。
原本以為這樣就可以拉到寄信的結果,結果我發現一直都是回應 Cancelled ,研究了很久,最後發現因為前面是使用 using 去叫 SmtpClient ,所以他事情做完就自動去 Dispose(),但是現在改用非同步模式去寄信,所以一Send SmtpClient 就被清掉,自然是不會有結果的(我猜他Dispose()時有可能自動做了SendAsyncCancel()還是因為物件不見就怎樣的關係),最後我改了寫法,長的像下面這樣。
使用SendAsync寄的時候,因為非同步的關係,所以會多要你傳一個token來辨識這是哪封信的結果,這在寄多封信的時候很有用,我這邊只寄一封信我就不理他了,詳情可以參閱SmtpClient.SendAsync 方法 (MailMessage, Object)。
基本上這樣就可以成功的用Gmail去幫你寄信了,這在自己做測試或監控,需要小量寄信的時候很方便,當然這段程式再延展起來也是可以拿來寄電子報、會員信之類的,就看你怎麼發揮了。
最後附上寄成功的信件內容,收工。
歐對了,我這個頁面的需求是會把QueryString "result"的內容寄出去,所以會多一小段東西,不然會更簡潔一點。
找了一下,.NET有這個SmtpClient 類別可以來寄信,而且sample code也蠻詳細的,所以就來試一下了。
我是直接用需要帳號密碼登入才能用的gmail來寄,一開始的code是長這樣
private const string Username = "username"; //update your gmail acc/pw here private const string Passowrd = "passowrd"; private string MailBody { get { return string.IsNullOrEmpty(Request.QueryString["result"]) ? string.Empty : Request.QueryString["result"]; } } protected void Page_Load(object sender, EventArgs e) { if (MailBody == string.Empty) return; using(var smtpServer = new SmtpClient("smtp.gmail.com", 587) { EnableSsl = true, Timeout = 10000, DeliveryMethod = SmtpDeliveryMethod.Network, Credentials = new NetworkCredential(Username, Passowrd) }) { smtpServer.Send(new MailMessage("[email protected]", "[email protected]", "test", MailBody) { BodyEncoding = Encoding.UTF8, DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure }); } }
其實這樣就可以寄了,但是拿不到成功或失敗的訊息,所以後來又加了SmtpClient.SendCompleted Event來去抓回應,這邊除了加上SendCompleted Event,寄信時原本是用.Send也要改成SendAsync,然後因為改成非同步模式,所以如果你在webpage上做的話,必須在 .aspx 的 <%@ Page %> 內加上 Async="true" ,不然會有錯誤訊息的。
原本以為這樣就可以拉到寄信的結果,結果我發現一直都是回應 Cancelled ,研究了很久,最後發現因為前面是使用 using 去叫 SmtpClient ,所以他事情做完就自動去 Dispose(),但是現在改用非同步模式去寄信,所以一Send SmtpClient 就被清掉,自然是不會有結果的(我猜他Dispose()時有可能自動做了SendAsyncCancel()還是因為物件不見就怎樣的關係),最後我改了寫法,長的像下面這樣。
private const string Username = "username"; //update your gmail acc/pw here private const string Passowrd = "passowrd"; private string MailBody { get { return string.IsNullOrEmpty(Request.QueryString["result"]) ? string.Empty : Request.QueryString["result"]; } } protected void Page_Load(object sender, EventArgs e) { if (MailBody == string.Empty) return; var smtpServer = new SmtpClient("smtp.gmail.com", 587) { EnableSsl = true, Timeout = 10000, DeliveryMethod = SmtpDeliveryMethod.Network, Credentials = new NetworkCredential(Username, Passowrd) }; var message = new MailMessage("[email protected]", "[email protected]", "test", MailBody) { BodyEncoding = Encoding.UTF8, DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure }; smtpServer.SendCompleted += SendCompletedCallback; try { smtpServer.SendAsync(message, "token"); } catch (Exception ex) { Label1.Text = ex.Message; } } private void SendCompletedCallback(object sender, AsyncCompletedEventArgs e) { // Get the unique identifier for this asynchronous operation. var token = (string)e.UserState; if (e.Cancelled) { Label1.Text = String.Format("[{0}] Send canceled.", token); return; } Label1.Text = e.Error != null ? String.Format("[{0}] {1}", token, e.Error) : String.Format("Message [{0}] sent.", token); }
使用SendAsync寄的時候,因為非同步的關係,所以會多要你傳一個token來辨識這是哪封信的結果,這在寄多封信的時候很有用,我這邊只寄一封信我就不理他了,詳情可以參閱SmtpClient.SendAsync 方法 (MailMessage, Object)。
基本上這樣就可以成功的用Gmail去幫你寄信了,這在自己做測試或監控,需要小量寄信的時候很方便,當然這段程式再延展起來也是可以拿來寄電子報、會員信之類的,就看你怎麼發揮了。
最後附上寄成功的信件內容,收工。
歐對了,我這個頁面的需求是會把QueryString "result"的內容寄出去,所以會多一小段東西,不然會更簡潔一點。
No comments:
Post a Comment