[VBNET] CDO 的使用

在網路上回過很多篇 CDO 的使用與方法,以這篇討論緒為主題,用回應來串接各個應用例。
 
這樣對於未來新增應用例也可以串到這個主題下,要瀏覽本文相關應用例,請點選永久連結或回應。
廣告
Categories: 技術分享 | 5 則迴響

文章分頁導航

5 thoughts on “[VBNET] CDO 的使用

  1. 子璉

    本篇回應下面標題及網址,如需瀏覽前後文或後續討論請點選該網址。
     
    使用System.net.mail可不可以發出約會或是約會邀請
    http://forums.microsoft.com/msdn-cht/ShowPost.aspx?PostID=781397&SiteID=14

    請參考 RFC 2445, 2446, 2447 製作 vCalendar 格式文件,製作完的格式若以 utf8 存為 xxxx.ics 後(不含檔頭),可被 Outlook 正常開啟時,則成功一半。
    由於 .Net framework 1.1/2.0 都是呼叫 CDO ,所以我也是直接呼叫 CDO ,下面是一段測試程式碼,若你的 strBody 為正確 vCalendar 格式時,就可以正常發送,並被 Outlook 2003 解讀,同意參加會議也是類似的文件。
    開發測試時,建議你同時用 OE 收該邀請信來比對,OE 的 eml 格式為原始郵件格式,你可以依據該格式來修改。
    這部分我覺得 RFC 寫的太凌亂了,要前前後後翻閱比對,若是要能正常完成,也要花個好幾天唸。我先前在下面那個位置有 ASP 行事曆原始碼,這次在 VBNET 改成支援邀請功能,且還沒寫全,就花了快一天才完成,才進行測試,等到程式碼整理乾淨了會再放到我那邊的原始碼分享區。
    http://tlcheng.twbbs.org/TLCheng/Basic/vbs/asp/Calendar.htm
    發信範例程式碼:
    Function SendInviteCalendar(ByVal strSubject As String, ByVal strBody As String, ByVal strFrom As String, ByVal strToUser As String, Optional ByVal strToCC As String = "", Optional ByVal strToBCC As String = "") As String
      Dim rtnString As String = ""
      Dim iMsg As Object = CreateObject("CDO.Message")
      Dim iConf As Object = CreateObject("CDO.Configuration")

     With iConf.Fields
       .Item("http://schemas.microsoft.com/cdo/configuration/sendusing ") = 2
       .Item("http://schemas.microsoft.com/cdo/configuration/smtpserver ") = "msa.hinet.net"
       .Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport ") = 25
       .Update()
      End With
      With iMsg
       .Configuration = iConf   ‘ 回傳發信人
       .Fields("urn:schemas:mailheader:Disposition-Notification-To") = strFrom   ‘ 重要性
       .Fields("urn:schemas:mailheader:importance") = 2
       .Fields("urn:schemas:mailheader:content-type") = "text/calendar; method=REQUEST; charset = ""utf-8"""
       .Fields("urn:schemas:mailheader:content-transfer-encoding") = "8bit"
       .Fields.Update()
       With iMsg.BodyPart
        Dim Stm As Object = .GetDecodedContentStream
        Stm.WriteText(strBody)
        Stm.Flush()
       End With
       .Organization = "HISDT 風禹科技驗證有限公司"
       .From = strFrom
       .To = strToUser
       .CC = strToCC
       .BCC = strToBCC
       .Subject = strSubject
       Try
        .Send()
       Catch ex As Exception
        rtnString = ex.Message
       End Try
      End With
      Return rtnString
    End Function

    喜歡

  2. 子璉

    本篇回應下面標題及網址,如需瀏覽前後文或後續討論請點選該網址。
     
    Mail Server (這篇是觀念,寄信的問題)
    http://forums.microsoft.com/MSDN-CHT/ShowPost.aspx?PostID=721405&SiteID=14
    本篇其他相關網址:
    http://forums.microsoft.com/msdn-cht/ShowPost.aspx?PostID=724614&SiteID=14
    http://forums.microsoft.com/msdn-cht/ShowPost.aspx?PostID=741975&SiteID=14
     
    基本上不建議往本機送,因為為了防止廣告信,很多信箱是只收可反查 DNS 、靜態位置等郵件,使用既有 smtpServer 沒問題時,就有可能是你的發信 ip 可能被擋了,所以你的信從網頁發到本機的 SMTP Server ,但是本機的 SMTP Server 要跟對方郵件伺服器溝通時,對方不接受,這類型要追蹤看錯誤訊息才知道。

    1. 郵件是透過 SMTP 協定一路轉發。
    client -> (寄件伺服器) -> (收件伺服器) ,若有內部信箱則會再轉發一次,到最後的位置,才由使用者透過 POP3 收信。
    在 client 端到寄件伺服器就是你平常的收發郵件方式,你可以用 OE、Outlook、或是利用程式寄信。這邊過濾機制一般有三種,帳號認證、認發信 IP 、POP3 連線後數分鐘內允許。前面說在本機設定允許 client 127.0.0.1 ,就是屬於認發信 IP 的方法,大部分 ISP 業者都會允許該網路用戶使用,比如說 msa.hinet.net 允許所有 HiNet 用戶直接寄信,這樣就不用自己架寄件伺服器。不過這部份另外還有收件者的上限,比如說 HiNet 好像是限制單一封信件不能超過 300 還 500 個收件者。有些可能會做寄件者信箱驗證。
    寄件伺服器送到收件伺服器過去是沒有阻攔,由於廣告業者太猖狂,前幾年有開協調會,原則上凡是動態 IP 的業者都會被阻攔,此外,國際上還有黑名單伺服器可下載設定,這部份目前只有認 IP 的方式,廣告信就是把自己當成寄件伺服器,直接發信,一般寄件伺服器對收件伺服器也有限制單一封信件收件者不能太多,各家業者限制不同,一般來說設定約在 20 ~ 500 人左右,在廣告信軟體為了避免被鎖,通常單一收件伺服器一封 5 ~ 10 人,有些可能會做 DNS 反查,也就是看寄件伺服器所取的域名跟 DNS 反查的 IP 是否一致。一般信件會延遲,就是在寄件伺服器到收件伺服器這段在慢,有的伺服器是排程定時批次發送,若是寄件伺服器無法連上收件伺服器,會排程重發,所以有時候會接到好幾天前的退信通知,這要看 SMTP Server 的設定。
    你現在的信是卡在寄件伺服器上,不是在 client 端,所以是寄件伺服器到收件伺服器這段的問題,對於收件伺服器看到你寄件伺服器的 IP 是路由出去的真實 IP ,所以要確認你的域名是否對映在這個 IP 上,你的 IP 是否是靜態 IP 等。
    所以一開始說,直接用現成的 SMTP Server 即可,比如說公司有 mail.abc.com.tw 的 SMTP Server ,直接設這台就可以了。
    2. 因為錯誤不是發生在程式上,所以你要追蹤的是 SMTP Server 的錯誤訊息,不是程式的,程式把信發到寄件伺服器後,對程式來說,就是正常執行完畢了,當然抓不到任何錯誤。要測程式有沒有問題當然就是先用給 Outlook之類軟體用的 SMTP Server 。
    當然你可以用 telnet 對方信箱 25
    然後自己 Key 指令來測。

    1.
    所以說可以直接設 ISP 的 Mail Server 阿~
    也有可能是拒收的 IP ,或是防火牆、路由器設定不正確,導致無法連結對方主機,如果不熟 SMTP 通訊協定,也可以在命令列測試:
    telnet 收件伺服器 25
    如果畫面會變全黑,就表示防火牆、路由設定正確,就只剩對方如何過濾寄件伺服器的問題了。
    2.
    我自己是直接在 .Net 存取 CDO ,不使用 .Net 的 Mail 類別,這部分是 CDO.Message.Fields.Update 無法更新,請貼你的設定範例來看。
    比如說設定為 hinet 發信伺服器用的字串為 "msa.hinet.net"
    0. 我貼一段我的程式碼,為簡單起見,部分額外屬性設定省略,所以你會看到部份引數無作用:
    Public Function SendMail(ByVal strMailServer As String, ByVal strFrom As String, ByVal strToUser As String, ByVal strSubject As String, ByVal strBody As String, ByVal strSender As String, Optional ByVal bReturnFrom As Boolean = False)
      Dim iBp, Flds As Object
      Dim Cfg As Object = CreateObject("CDO.Configuration")
      Dim iMsg As Object = CreateObject("CDO.Message")
      Dim encStream As Object
      Cfg.Fields("http://schemas.microsoft.com/cdo/configuration/sendusing ") = 2
      Cfg.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserver ") = strMailServer
      ‘Cfg.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserverport ") = 25           ‘standard port for SMTP (default)
      Cfg.Fields.Update()
      With iMsg
       .Configuration = Cfg
    ‘… 略
          ‘ 回傳發信人
       If bReturnFrom Then
        .Fields("urn:schemas:mailheader:Disposition-Notification-To") = strFrom
       End If
       .Fields.Update()
       .MimeFormatted = False
       .AutoGenerateTextBody = False
       .Organization = "HISDT 風禹科技驗證有限公司"
       .From = strFrom
       .To = strToUser
       .Subject = strSubject
       .TextBody = strBody
       On Error Resume Next
       .Send()
       If Err.Number <> 0 Then
        SendMail = Err.Description
        Err.Clear()
       End If
       On Error GoTo 0
      End With
      Flds = Nothing
      iBp = Nothing
      Cfg = Nothing
      iMsg = Nothing 
    End Function

    你可以先把你的記錄檔啟用,並開啟所有擴充項目(如果你不知道該紀錄哪些項目時)
    例如說我用個偽造的寄信位置,就會被拒絕,可以在記錄檔找到:
    13:49:32 168.95.5.5 OutboundConnectionResponse SMTPSVC1 – – 451+<devil@tainan.com.tw.x>…+Sender+domain+must+exist 0 0 55 0 15656 SMTP – – –
    紅色的就是錯誤訊息,上面寫的很清楚,寄送者的網域必須存在,此例中的 tainan.com.tw.x 並不存在。
    SMTP 基本觀念可以參考 RFC 內的文件,不過你現在是管理問題,不太需要看 SMTP 的基本通訊,則看看 Exchange 的書有沒有針對這類管理問題做彙整。此外,你在使用 SMTP 服務時,也可以先參考微軟的線上說明書,裡面有針對各欄位做說明。
    你是寄信被拒,也可以參考一些寄件伺服器軟體的 FAQ ,因為這些都是相通的。
    另外純粹 SMTP 設定問題,建議你到舊討論區的 Exchange 去討論,那邊比較多 MIS ,但是你必須針對你的問題、設定及網路狀況說明清楚,這樣大家才能給你參考意見。
    我自己在用沒碰上啥問題,而你沒有提供錯誤訊息、網路狀況可供參考,我也沒辦法提供更多的參考資訊。

    之所以前面會建議你使用既有的 寄件伺服器 ,就是要把程式開發問題跟管理問題切開來,程式沒問題後,基本上剩下的事可以丟給單位的網路管理者,基本上我並不建議在每台 IIS 都啟用 SMTP 服務,除了吃資源、硬碟等,這是管理上的困擾,一個單位可能會有很多網站分別在不台電腦上,但是不需要有很多台寄件伺服器,僅需要一台即可,出問題時,網管人員只需要查一台即可。
    甚至基於網路資源的考量下,用外面公司的會更省。比如說你單封信要轉發給 100 人,假設分屬於 100 台收件伺服器,則同一封信要由你的寄件伺服器分成 100 封送給不同的收件伺服器,若是一封為 10 kb ,則需要 1 gb 傳輸量,但是你若是用 ISP 業者提供的寄件伺服器,你只要傳一封到 ISP 業者那去,你的上傳流量只需要 10 kb (另需加上收件清單) ,若是民間中小企業,網路上傳頻寬只有個 512k 甚至更小 (相當 64kb/s),省下來的流量可以做很多事,網頁也可以服務的更順暢。
    整個 MSDN 討論區基本上是程式開發討論區,新的管理討論區已經在測試了,將來可以到那區討論管理問題,目前請到舊討論區討論。
     
    1.
    附件方式:
    http://msdn.microsoft.com/library/en-us/wss/wss/_cdo_imessage_addattachment.asp
    MIME HTML 方式:
    http://msdn.microsoft.com/library/en-us/wss/wss/_cdo_imessage_createmhtmlbody.asp
    2. 標準寫法:"中文字串" <jsmith123@example.com> ,只要是寄件、收件欄位都支援。
    VB語法中,要在字串中加入 " 要用 "" 表示。
    .From = """寄件者"" <sender@mail.your.com.tw>"

    喜歡

  3. 子璉

    本篇回應下面標題及網址,如需瀏覽前後文或後續討論請點選該網址。
     
    請問內嵌圖片郵件發送功能要怎麼做?http://forums.microsoft.com/msdn-cht/ShowPost.aspx?PostID=435571&SiteID=14
    CreateMHTMLBody 其他相關討論:
    http://forums.microsoft.com/msdn-cht/ShowPost.aspx?PostID=1020743&SiteID=14
    http://forums.microsoft.com/msdn-cht/ShowPost.aspx?PostID=435571&SiteID=14
     

    你如果沒有帳號密碼問題,可以直接用 CDO 的
    Message.CreateMHTMLBody(strUrl)
    這樣會自動幫你把 CSS / Script / 圖檔 (含背景,不含 VML 語法底圖) / 音效 封起來寄出去。
    用 .Net 的寄件類別可以用
    Dim writer As New IO.StringWriterServer.Execute(strUrl, writer)Dim strHTML As String = writer.ToString()
    來執行你的動態網頁,可依 Session 將帳號密碼傳給指定網址,但 CSS / Script / 圖檔 / 音效 等則要自行 code 編碼加進去,或是崁進去。
     

    喜歡

  4. 子璉

    本篇回應下面標題及網址,如需瀏覽前後文或後續討論請點選該網址。
     
    請問要如何得知對方有無收到Email和開啟Mail內容?http://forums.microsoft.com/msdn-cht/ShowPost.aspx?PostID=450539&SiteID=14
     
     
    傳遞可用這個屬性:DeliveryNotificationOptions
    讀信通知的話,.Net 2.0 看來沒包,我是直接用 CDO 來處理,下面討論區隨便找一篇來轉寄,收信時會通知轉寄者。
    http://tlcheng.no-ip.com/News/Reader.aspx?Newsgroup=microsoft.public.tw.dotnet.framework.aspnet&Action=List
    .Net 2.0 的話,你試看看在 MailMessage.Headers 集合加入:
    MailMessage.Headers.Add("Disposition-Notification-To","""使用者"" <someone@forums.microsoft.com.x>")
    收到後跟上面那封比較信頭看看,若是一樣的話,應該會問你要不要傳遞讀信訊息回去。

    喜歡

  5. Tommy

    Thanks~

    喜歡

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s

在WordPress.com寫網誌.

%d 位部落客按了讚: