VFP 愛用者社區 首頁 VFP 愛用者社區
本討論區為 Visual Foxpro 愛用者經驗交流的地方, 請多多利用"搜尋"的功能, 先查看看有無前例可循, 如果還有不懂的再發問. 部份主題有附加檔案, 須先註冊成為社區居民才可以下載.
 
 常見問題常見問題   搜尋搜尋   會員列表會員列表   會員群組會員群組   會員註冊會員註冊 
 個人資料個人資料   登入檢查您的私人訊息登入檢查您的私人訊息   登入登入

用 VFP 發送帶附件的電子郵件(轉貼)

 
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區
上一篇主題 :: 下一篇主題  
發表人 內容
goto-dream



註冊時間: 2004-05-11
文章: 909


第 1 樓

發表發表於: 星期六 九月 25, 2004 1:46 am    文章主題: 用 VFP 發送帶附件的電子郵件(轉貼) 引言回覆

用 VFP 發送帶附件的電子郵件
http://202.195.143.200/gonggong/800/vfp/jishu/007.htm

Doug Hennig 提供一個可用於從應用程序中發送 e-mail 的類. 它組合兩個 MAPI ActiveX 控件到一個易於使用的類中.

在今天,許多許多用戶希望能在他們的應用程序中發送 e-mail. 例如, 典型的商業應用程序中的客戶表單中可能有一字段用於保存客戶的 e-mail 地址. 在這樣的應用程序中,沒有一種快速的、不需要切換到 Outlook Express 並複製和粘貼它們的 e-mail 地址的方法(如表單或工具欄上的按鈕或菜單項) 來發送一個 e-mail 給客戶是一種羞恥. 雙倍的羞恥是由於 添加該功能到 VFP 應用程序是如此容易. 本文探討一些可用於從你的應用程序中發送 e-mail 的一些類.

MAPI ActiveX controls
要使用應用程序可以發送 e-mail 的最簡單的方法是使用 VFP 自帶的MAPI ActiveX 控件. 有兩個相關控件, 都在文件 MSMAPI32.OCX 中: MAPIMessages 和 MAPISession. 這些控件一起工作-MAPISession 控件負責管理由件會話期, MAPIMessages 控件用於發送和接收信息. 兩個控件都是非可視的. 你可以將它們拖放到表單中或用代碼 CREATEOBJECT 來實例它們(這些控件的ProgIDs 是 MSMAPI.MAPIMessages 和 MSMAPI.MAPISession).
這些控件的屬性, 事件和方法 (PEM) 在幫助文件 MAPI98.CHM 中描述(位於我的系統中的 \WINDOWS\HELP 目錄). 代替描述如何使用這些控件, 我們將探討一個我創建的組合兩個控件到一個易於使用的對象的容器類. 我們將明白ActiveX 的 PEM 是如何用於我們正在探討的類的代碼中的. 另外, 雖然這些控件可以發送和接收郵件, 本文將只著重於發送信息.

SFMAPI
為了隱藏兩個控件的複雜的處理, 我創建了 SFMAPI 類 (在 SFMAPI.VCX 中). SFMAPI 是基於 SFContainer 容器類的, 我們的容器基類在 SFCTRLS.VCX 中定義. 它包括一個 MAPIMessages 控件 (名為 oMAPIMessage 在 SFMAPI 中) 和一個 MAPISession 控件 (oMAPISession). 我設置容器的 Visible 屬性為 .F. (由於它是一個在運行時非可視的控件) 並添加了一系列的屬性: aAttachments, 一個用於保存與信息相關的文件名的受保護的數組; aRecipients, 一個收件人信息的受保護的數組; cMessage, 要發送的信息體; cSubject, 信息主題; lLoggedIn, 一個受保護的屬性,如果成功登錄到 MAPI 則它的值為.T.; 以及 lSignoffAfterSend, 若為 .T. 意味著 SFMAPI 將在發送完信息後中止聯接 MAPI 會話期.
要用 SFMAPI 發送一條信息, 用調用 NewMessage 方法開始. 該信息簡單地初始化 aRecipents 和 aAttachments 為單純的空的入口; 它只在你以前用該對像發送過信息才真正地需要. 其次, 為每一個接受者調用 AddRecipient 方法一次, 傳遞 e-mail 地址和可選的接受者名字和類別 (1是主要接受者, 2是複製接受者, 3是 blind 複製接受者). 該方法在確信 aRecipients 數組是可用的後, 添加傳遞的信息到 aRecipients 數組:


lparameters tcAddress, ;
tcName, ;
tnType

local lcName, ;
lnType, ;
lnCount
assert vartype(tcAddress) = 'C' and ;
not empty(tcAddress) ;
message 'Invalid address specified'
lcName = iif(type('tcName') <> 'C' or empty(tcName), ;
tcAddress, tcName)
lnType = iif(type('tnType') <> 'N' or ;
not between(tnType, 1, 3), 1, tnType)
with This
lnCount = iif(empty(.aRecipients[1, 1]), 1, ;
alen(.aRecipients, 1) + 1)
dimension .aRecipients[lnCount, alen(.aRecipients, 2)]
.aRecipients[lnCount, 1] = lcName
.aRecipients[lnCount, 2] = tcAddress

.aRecipients[lnCount, 3] = lnType
endwith

如果信息有任何附件, 調用 AddAttachment 方法, 它與 AddRecipient 類似但添加指定的文件名到 aAttachments 數組.
最後, 設置 cSubject 屬性為信息主題, 設置 cMessage 為信息體, 並調用 Send 方法. 如果想顯示對話框傳遞 .T.. 注意當從 VFP 5 中調用該方法時,你必須這樣做,以避免一個 "不可用的調用" 錯 (在 VFP 6 中不會出現該錯誤).
我們將探討一下 Send 方法的代碼. 它開始時確保至少有一個接收者, 然後,如果還沒有登錄到 MAPI則調用 SignOn 方法 (我們馬上就要看到). 如果失敗, Send 返回 .F.

lparameters tlDisplayDialog
local lnI
with This

* 確信至少有一個接收者.

assert not empty(.aRecipients[1, 1]) ;
message 'SFMAPI.Send: no recipients'

* 如果還沒有登錄, 試著登錄. 如果不能登錄, 返回 .F.

if not .lLoggedIn and not .SignOn()
return .F.
endif
接著, 它設置 MAPIMessages 對象的 SessionID 屬性為MAPISession 對象的屬性值, 這樣 MAPIMessages 對象可以和 MAPI 通信; 這與用 FOPEN() 函數打開文件時使用文件句柄相似. 它調用 MAPIMessage 的 Compose 方法來啟始一個新的信息, 並設置MsgNoteText 和 MsgSubject 屬性為它的 cMessage 和 cSubject 值.

.oMAPIMessage.SessionID = .oMAPISession.SessionID
.oMAPIMessage.Compose()
.oMAPIMessage.MsgNoteText = .cMessage
.oMAPIMessage.MsgSubject = .cSubject

下一步是告訴 MAPIMessages 對像關於收件人. MAPIMessages 對象的一個內部的、以離奇的方式表述的收件人集合: 由 RecipIndex 屬性指明的、與收件人相關的屬性綁定到當前的內部收件人. 你設置 RecipIndex 為你想處理的收件人索引 (索引是以0為基數的, 所以第一個收件人的索引是 0), 和適當的 MAPIMessages 屬性以便讀取和寫到選定的收件人. 要添加一個新的收件人, 設置 RecipIndex 為一個大於當前收件人數的值 (事實上, 等於收件人人數, 因為索引是以0為基數的), 它是保存在 RecipCount 屬性中; 這樣做自動增加 RecipCount. 我們感興趣的、與收件人相關的屬性是 RecipDisplayName (顯示給用戶的收件人名字), RecipAddress ( e-mail 地址), 以及 RecipType (收件人類型, 我在前面討論過的範圍值). 設置了這些屬性後, 調用 ResolveName 方法來從地址薄中分解名字同樣是必須的.
寫收件人信息到 MAPIMessages 對象的代碼遍歷 aRecipients 數組, 設置收件人索引來添加另一個收件人並新收件人的適當的屬性.

for lnI = 1 to alen(.aRecipients, 1)
.oMAPIMessage.RecipIndex = ;
.oMAPIMessage.RecipCount
.oMAPIMessage.RecipDisplayName = .aRecipients[lnI, 1]
.oMAPIMessage.RecipAddress = .aRecipients[lnI, 2]
.oMAPIMessage.RecipType = .aRecipients[lnI, 3]
.oMAPIMessage.ResolveName()
next lnI
附件中的文件處理非常簡單: AttachmentIndex 屬性指明哪一個內部的附件要發送, 以及 AttachmentPosition, AttachmentPathName 和 AttachmentName 屬性是綁定到當前附件. AttachmentPathName (附件的完整的名字和路徑) 和 AttachmentName (收件人將看到的附件的名字) 是簡單易懂的, 但是 AttachmentPosition 是離奇的: 它指明附件將在信息體內的地方. 我不能知道, 為什麼附件要與信息體發生聯繫, 但是由於沒有兩個附件可以出現在相同的位置, 而且沒有附件可以放在遠離信息尾的地方, 我決定放置它們到信息的開頭 (位置是以0為基數的; 因此在以下代碼中是1).


for lnI = 1 to alen(.aAttachments)
if not empty(.aAttachments[lnI])
.oMAPIMessage.AttachmentIndex = ;
.oMAPIMessage.AttachmentCount
.oMAPIMessage.AttachmentPosition = lnI - 1
.oMAPIMessage.AttachmentPathName = .aAttachments[lnI]
.oMAPIMessage.AttachmentName = ;
justfname(.aAttachments[lnI])
endif not empty(.aAttachments[lnI])
next lnI
最後, 我們需要調用 MAPIMessages 對象的Send 方法來發送信息. 如果我們假定要顯示一個對話框 (正如我在先前提及, 在 VFP 5 中必須這樣做), 傳遞值 1 到 Send. 然後我們調用 SignOff 方法 (假定發送信息後掛斷). 你可能認為返回MAPIMessage 的 MsgSent 屬性值是有意義的(它指明郵件是否成功的發送到了郵件服務器; 但它不能指明郵件是否會成功地從郵件服務器發送出去) 但出於一些理由, 對於我來說,該屬性總是返回 .F..

if tlDisplayDialog
.oMAPIMessage.Send(1)
else
.oMAPIMessage.Send()
endif tlDisplayDialog
if .lSignOffAfterSend
.SignOff()
endif .lSignOffAfterSend
endwith
受保護的 SignOn 方法, 如果我們還沒有登錄到 MAPI 就從 Send 方法中調用它來登錄到 MAPI. 它首先確保 MAPI32.DLL 可以在 Windows System 目錄中找到 (GetSystemDirectory API 函數用於定位該目錄), 然後設置 MAPISession 對象的 DownloadMail 屬性為 .F. (此時我們只想發送郵件) 和 LogonUI 屬性為 .F. (如果我們想顯示一個登錄對話框讓用戶輸入他們的名字和口令, 設置該屬性為 .T.). 它調用 MAPISession 的 SignOn 方法來執行登錄到 MAPI, 然後設置 SFMAPI 的 lLoggedIn 屬性為 .T.(如果 MAPISession 的 SessionID 屬性大於 0). 如果登錄成功, 方法返回 .T..

local lcDirectory, ;
lnLen
with This
* 如果沒有找到 DLL 則沒有必要試著登錄到 MAPI.

declare integer GetSystemDirectory in Win32API ;
string @, integer
lcDirectory = replicate(chr(0), 80)
lnLen = GetSystemDirectory(@lcDirectory, 80)
lcDirectory = addbs(left(lcDirectory, lnLen))
* 可以找到它, 因此設置一些屬性並試著登錄.

if file(lcDirectory + 'MAPI32.DLL')
.oMAPISession.DownloadMail = .F.
.oMAPISession.LogonUI = .F.
.oMAPISession.SignOn()
.lLoggedIn = .oMAPISession.SessionID > 0
else
messagebox('Cannot find MAPI32.DLL')
.lLoggedIn = .F.
endif not file(lcDirectory + 'MAPI32.DLL')
endwith
return This.lLoggedIn
受保護的 SignOff 方法, 在 lSignOffAfterSend 屬性為 .T. 時從 Send , Destroy 方法和 Error 方法中調用, 用於掛斷 MAPI 和設置 lLoggedIn 屬性為 .F.

with This.oMAPISession
if .SessionID <> 0
.SignOff()
endif .SessionID <> 0
endwith
This.lLoggedIn = .F.
示例表單
TESTMAPI.SCX 是一個演示 SFMAPI 的表單. 它看起來像一個典型的客戶數據輸入表單, 帶有名字, 地址等文本框等. 它還有一個輸入客戶的 e-mail 地址的文本框. 該文本框前面的標籤是黑體字的 (向用戶顯示它是特別的) 且在其 DblClick 方法中有以下代碼:


with Thisform.oMAPI
.AddRecipient(alltrim(Thisform.txtEmail.Value))
.Send(.T.)
endwith
當你雙擊該標籤時, 這些代碼添加 e-mail 文本框中的值作為收件人並調用 SFMAPI 控件的 Send 方法, 並傳遞參數 .T. 因此顯示一個對話框. 注意 cSubject 和 cMessage 屬性沒有設置; 畢竟, 我們不知道用戶想如何設置這些值, 因此它們可以在顯示的對話框中輸入需要的信息.
你可以為用戶提供其它方法來發送一個 e-mail: 一個在 e-mail 文本框旁邊的命令按鈕, 一個表單上或工具條上的按鈕, 一個菜單項等等. 眾所周知的 VFP 頭子 Markus Egger 創建了一個聰明的機製作為 Visual LandPro 的一部分, ( Visual LandPro 是一個幫助開發的應用程序, 曾被選為兩年一度的 VFP Excellence Awards(VFP 傑出成就獎)決賽程序). 它創建一個顯示 e-mail 地址為一個熱連接的文本框 (就是說, 它在白色的背景中顯示一個蘭色的下劃線文本). 用戶單擊它, 就像它們是一個熱連接一樣, 要發送一個信息到該地址. 關於他的類中的偉大的東西是你甚至不必向大數用戶解釋它是如何工作的.
結論
由於添加 e-mail 能力到一個應用程序簡單到拖動一個 SFMAPI 對像到表單中, 設置它的屬性, 並在用戶指出他們想發送一個 e-mail 時調用一些方法, 沒有理由不添加這種能力到那怕是最簡單的應用程序中.
下個月, 我們將探討一些發送郵件列表到一組人的可重用工具: 它們提供大多數郵件列表基礎(不, 我不是午餐肉擁護者; 有很多合法的理由來發送相同的郵件到一組人). 到那時, 我希望你喜歡那些類.

_________________
福隆昌淨水有限公司--淨水器的專家,淨水器,飲水機,濾心!!

想了解更多,您可上幸福雞湯組.找尋!!丁澐瑄.老師.

          愛作夢
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件
garfield
Site Admin


註冊時間: 2003-01-30
文章: 2157


第 2 樓

發表發表於: 星期三 五月 18, 2005 5:10 pm    文章主題: 引言回覆

一直都找不到問題, 為什麼 在outlook Express沒問題, 但在 outlook 都一直有問題.
在用 outlook 時會出現 Unspecified Failure has occurred.
花了我半天時間一直在找資料測試, 最後終於找到答案了:

http://www.prd-software.com.au/prd/support/kb/kbarticle.asp?id=83


The Information in this article applies to:
HelpMaster Pro: Desktop (all supported versions upto/incl 5.x.x)
This article resides in the following categories:
E-mail
See also:
KB Article Number: 83
Error Number: 32002
Created: 1/31/2001
Last Updated: 1/31/2001
Current User Rating:67%


Summary
There are two known possible causes of this error.

The above error may occur when attempting to send E-mail through HelpMaster Pro. HelpMaster Pro attempts to send all E-mail through your systems default MAPI compliant mail system. This error can occur if your chosen E-mail system has not been set as the default MAPI client for your PC and the current default MAPI client is not correctly configured.
Sending a blank E-mail with an attachment.
Resolution
You can set your systems default mail program through "Internet Options" found in your Control Panel. On the Programs Tab you will find an "E-mail:" Drop-down box. Select your preferred mail application from this list and press the Apply button.

If your mail system does not appear in that drop-down box, or if E-mail still does not work consult its help file to establish if it is (or can be set up to be) MAPI compliant, and for more information about setting it up as the default MAPI client on your workstation.

Enter some text into the body of the E-mail and this error will not occur.

************
原因是:
email 內文(容)不可以空白
猪頭 Confused
將答案貼上來, 這樣下一個找到這篇文章的猪頭, 就可安心了.
*********
又發現一個會出現這個問題的狀況:
附加檔案有別的程式正在開啟中.

_________________
利用>>搜尋<<的功能會比問的還要快得到答案.
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件
mp484



註冊時間: 2006-08-08
文章: 84


第 3 樓

發表發表於: 星期六 十月 25, 2008 4:59 pm    文章主題: 引言回覆

在傳送前先檢查兩個錯誤的狀況:
1.連線狀況.....如果沒有連線就執行傳送也是會出現問題的(檢查連線狀態在論壇裡面有)
2.附加檔案是否存在......用File(cFile)檢查檔案是否存在,若要確認檔案是否為開啟中,則要用FOPEN()函數檢查,如果檔案不存在或在使用中都不可以成為附加檔案。

這兩個狀況都會造成在 Send(0)時發生錯誤的狀況,所以當發送郵件時事先警告並退出傳送工作,就可以避免錯誤的狀態發生。
回頂端
檢視會員個人資料 發送私人訊息
jerryclt



註冊時間: 2009-03-10
文章: 334
來自: 佛心來的

第 4 樓

發表發表於: 星期四 十一月 06, 2014 5:12 pm    文章主題: 引言回覆

阿娘喂...
豬頭+1 Crying or Very sad
回頂端
檢視會員個人資料 發送私人訊息
從之前的文章開始顯示:   
發表新主題   回覆主題    VFP 愛用者社區 首頁 -> VFP 討論區 所有的時間均為 台北時間 (GMT + 8 小時)
1頁(共1頁)

 
前往:  
無法 在這個版面發表文章
無法 在這個版面回覆文章
無法 在這個版面編輯文章
無法 在這個版面刪除文章
無法 在這個版面進行投票
無法 在這個版面附加檔案
無法 在這個版面下載檔案


Powered by phpBB © 2001, 2005 phpBB Group
正體中文語系由 phpbb-tw 維護製作