在Windows Mobile 6上通過CEMAPI 傳送簡訊

來源:互聯網
上載者:User

在Windows Mobile 6上通過CEMAPI POOM傳送簡訊

在Winodws Mobile上第三方軟體一般是通過
1)調用SmsMessageSend API函數傳送簡訊。
或者通過
2)CreateProcess或者ShellExecuteEx方式,調用命令(不含角括弧)
</windows/tmail.exe -service "SMS" -to "簡訊接收方號碼" -body "簡訊內容">

下面的例子,就是調用Windows Mobile內建的簡訊程式(tmail.exe),編輯一條收件者為10086,簡訊內容為 CXYE,查詢餘額的簡訊。
/windows/tmail.exe -service "SMS" -to "10086" -body "KTIP1000"
最終效果如。
<Place Holder for SMS Send UI>

1)和2)這兩種方法都有各自的優缺點。
第一種方法,簡訊發送成功後在微軟內建的已發送郵件箱(Sent Items)中找不到已經發送的簡訊。發送失敗也沒有提示。當然可以自己硬行構造POOM的簡訊對象來實現這個不足。
第二種方法,就是通過tmail.exe -service "SMS" -to "" -body "" 的方法不能夠自動傳送簡訊,只是停留在編輯完成介面,還需要使用者手動點擊"發送"按鈕,或者通過程式實現。

下面介紹一種方法既能夠讓已發簡訊出現在已發送郵件箱中,也能夠將簡訊編輯完成後自動發送。
這就是通過CEMAPI來傳送簡訊。這個在www.codeproject.com 上05年的一篇文章已經實現了。請原文請參考 http://www.codeproject.com/KB/mobile/SMS_CEMPI.aspx .

我使用和實踐了這段代碼,發現幾個問題。
1)傳送簡訊不成功後,簡訊會到草稿箱,但是點開改簡訊,再次發送時,就無法發送了。
<Place Holder for Screen shot>
此時,簡訊的內容放置到了主題(Subject)上,這和普通使用時候遇到的情況不一樣,簡訊內容應該在本文(Body)中.
2)簡訊發送時候,需要設定一個參數,那就是本機號碼。至於如何獲得本機號碼,是非常麻煩的。
3)此Sample是在EVC下編譯的,而且缺少.rc2檔案。雖然作者已經說明了如何解決。

但是我還是重新改寫了以下,將所有的CComPtr<IMAPISession> 之類的定義改成了WM6上建議的IMAPISession
改正了 SendSMSMessage 函數的HRESULT 類型傳回值 Return S_OK.

但是1)和2)的問題仍舊需要解決。
// --- SMSHelper.cpp ---<br />#include "Log.h"<br />#include "SMSHelper.h"<br />/////////////////////////////////////////////////////////////////////////////////////////////<br />// This function is used to get the msgstore named SMS from msgstores on the<br />// device.<br />// I could have used just raw pointers but it is much easier and safer to just<br />// use smart pointers.<br />HRESULT GetSMSMsgStore( IMAPISession* pSession, IMsgStore ** ppMsgStore)<br />{<br />// first we get the msgstores table from the session<br />IMAPITable * pTable=NULL;<br />HRESULT hr = pSession->GetMsgStoresTable(MAPI_UNICODE, &pTable);<br />if (FAILED(hr) && pTable!=NULL )<br />{<br />//MessageBox(NULL, L"Failed: GetMsgStoresTable", L"GetSMSMsgStore", MB_OK);<br />WriteString( L"Failed: GetMsgStoresTable - GetSMSMsgStore" );<br />return FALSE;<br />}<br />WriteString( L"Passed: GetMsgStoresTable - GetSMSMsgStore" );<br />// next we loop over the message stores opening each msgstore and<br />// getting its name to see if the name matches SMS.<br />// If it does then we break out of the loop<br />while (TRUE)<br />{<br />SRowSet* pRowSet = NULL;<br />hr = pTable->QueryRows(1, 0, &pRowSet);<br />// If we failed to query the<br />// rows then we need to break<br />if (FAILED(hr) && pRowSet!=NULL)<br />{<br />//MessageBox(NULL, L"Failed: QueryRows", L"GetSMSMsgStore", MB_OK);<br />WriteString( L"Failed: QueryRows - GetSMSMsgStore" );<br />break;<br />}<br />WriteString( L"Passed: QueryRows - GetSMSMsgStore" );<br />// if we got no rows back then just exit the loop<br />//remembering to set an error<br />if (pRowSet->cRows == 1)<br />{<br />ASSERT(pRowSet->aRow[0].lpProps->ulPropTag == PR_ENTRYID);<br />SBinary& blob = pRowSet->aRow[0].lpProps->Value.bin;<br />hr = pSession->OpenMsgStore(NULL, blob.cb, (LPENTRYID)blob.lpb, NULL, 0,ppMsgStore);<br />if (FAILED(hr))<br />{<br />//MessageBox(NULL, L"Failed: OpenMsgStore", L"GetSMSMsgStore", MB_OK);<br />WriteString( L"Failed: OpenMsgStore - GetSMSMsgStore" );<br />}<br />WriteString( L"Passed: OpenMsgStore - GetSMSMsgStore" );<br />}<br />else<br />{<br />//MessageBox(NULL, L"pRowSet->cRows != 1", L"GetSMSMsgStore", MB_OK);<br />WriteString( L"pRowSet->cRows != 1 - GetSMSMsgStore" );<br />hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);<br />}<br />// now remember to free the row set<br />FreeProws(pRowSet);<br />if (FAILED(hr))<br />{<br />break;<br />}<br />// now get the display name property from the<br />// message store to compare it against the name<br />// 'SMS'<br />SPropTagArray props;<br />props.cValues = 1;<br />props.aulPropTag[0] = PR_DISPLAY_NAME;<br />ULONG cValues;<br />SPropValue* pProps = NULL;<br />hr = (*ppMsgStore)->GetProps(&props, MAPI_UNICODE, &cValues, &pProps);<br />if (FAILED(hr) || cValues != 1)<br />{<br />//MessageBox(NULL, L"Failed: GetProps", L"GetSMSMsgStore", MB_OK);<br />WriteString( L"Failed: GetProps - GetSMSMsgStore" );<br />break;<br />}<br />WriteString( L"Passed: GetProps - GetSMSMsgStore" );<br />// if the name matches SMS then break and as<br />// hr == S_OK the current MsgStore smart pointer<br />// will correctly be set.<br />if (_tcsicmp(pProps[0].Value.lpszW, _T("SMS")) == 0)<br />{<br />break;<br />}<br />}<br />// if we failed for some reason then we clear out<br />// the msgstore smartpointer and return the error.<br />if (FAILED(hr) )<br />{<br />(*ppMsgStore)->Release();<br />}<br />return hr;<br />}<br />/////////////////////////////////////////////////////////////////////////////////////////////<br />// This function is used to get the folder named drafts from the msgstore on the<br />// device.<br />// I could have used just raw pointers but it is much easier and safer to just<br />// use smart pointers.<br />HRESULT GetSMSFolder(IMsgStore* pMsgStore, IMAPIFolder** ppFolder)<br />{<br />// Now get the Drafts folder.<br />SPropTagArray propDefaultFolder;<br />propDefaultFolder.cValues = 1;<br />propDefaultFolder.aulPropTag[0] = PR_CE_IPM_DRAFTS_ENTRYID;<br />ULONGcValues;<br />LPSPropValuepPropVals;<br />HRESULT hr = pMsgStore->GetProps (&propDefaultFolder, MAPI_UNICODE, &cValues, &pPropVals);<br />if (FAILED(hr))<br />{<br />//MessageBox(NULL, L"Failed: GetProps", L"GetSMSFolder", MB_OK);<br />WriteString( L"Failed: GetProps - GetSMSFolder" );<br />return hr;<br />}<br />WriteString( L"Passed: GetProps - GetSMSFolder" );<br />SBinary& eidDrafts = pPropVals->Value.bin;<br />hr = pMsgStore->OpenEntry(eidDrafts.cb, (LPENTRYID)eidDrafts.lpb, NULL, MAPI_MODIFY, NULL, (LPUNKNOWN*)ppFolder);<br />if (FAILED(hr))<br />{<br />//MessageBox(NULL, L"Failed: OpenEntry", L"GetSMSFolder", MB_OK);<br />WriteString( L"Failed: OpenEntry - GetSMSFolder" );<br />}<br />WriteString( L"Passed: OpenEntry - GetSMSFolder" );<br />return hr;<br />}<br />/////////////////////////////////////////////////////////////////////////////////////////////<br />// This function is used to get the send the message.<br />// This uses an opened MAPI session<br />HRESULT SendSMSMessage( ICEMAPISession * pSession, LPCTSTR lpszFrom, LPCTSTR lpszTo, LPCTSTR lpszMessage)<br />{<br />// now get the SMS message store<br />IMsgStore* pMsgStore = NULL;<br />HRESULT hr = GetSMSMsgStore(pSession, &pMsgStore);<br />if (FAILED(hr) && pMsgStore!=NULL)<br />{<br />//MessageBox(NULL, L"Failed: GetSMSMsgStore", L"SendSMSMessage", MB_OK);<br />WriteString( L"Failed: GetSMSMsgStore - SendSMSMessage" );<br />return hr;<br />}<br />WriteString( L"Passed: GetSMSMsgStore - SendSMSMessage" );</p><p>IMAPIFolder* pFolder=NULL;<br />hr = GetSMSFolder(pMsgStore, &pFolder);<br />if (FAILED(hr) && pFolder!=NULL )<br />{<br />//MessageBox(NULL, L"Failed: GetSMSFolder", L"SendSMSMessage", MB_OK);<br />WriteString( L"Failed: GetSMSFolder - SendSMSMessage" );<br />return hr;<br />}<br />WriteString( L"Passed: GetSMSFolder - SendSMSMessage" );</p><p>IMessage* pMessage=NULL;<br />hr = pFolder->CreateMessage(NULL, 0 ,&pMessage);<br />if (FAILED(hr) && pMessage!=NULL)<br />{<br />//MessageBox(NULL, L"Failed: CreateMessage", L"SendSMSMessage", MB_OK);<br />WriteString( L"Failed: CreateMessage - SendSMSMessage" );<br />return hr;<br />}<br />WriteString( L"Passed: CreateMessage - SendSMSMessage" );<br />// set the recipients<br />// set up the required fields for a recipient<br />SPropValue propRecipient[3];<br />// it is vital we clear the property structure<br />// as there are fields we do not use but MAPI seems<br />// to be sentative to them.<br />ZeroMemory(&propRecipient, sizeof(propRecipient));<br />// set the recipient type which coul be to, cc, bcc<br />// but ehre must at least be a to field<br />propRecipient[0].ulPropTag = PR_RECIPIENT_TYPE;<br />propRecipient[0].Value.l = MAPI_TO;<br />// we set the type of address to sms instead of<br />// smtp<br />propRecipient[1].ulPropTag = PR_ADDRTYPE;<br />propRecipient[1].Value.lpszW = _T("SMS");<br />// we finally set the email address to the<br />// phone number of the person we are sending the message<br />// to<br />propRecipient[2].ulPropTag = PR_EMAIL_ADDRESS;<br />propRecipient[2].Value.lpszW = (LPWSTR)lpszTo;<br />// set the addrlist to point to the properties<br />ADRLIST adrlist;<br />adrlist.cEntries = 1;<br />adrlist.aEntries[0].cValues = 3;<br />adrlist.aEntries[0].rgPropVals = (LPSPropValue)(&propRecipient);<br />// finally modify the recipients of the message<br />hr = pMessage->ModifyRecipients(MODRECIP_ADD, &adrlist);<br />if (FAILED(hr))<br />{<br />//MessageBox(NULL, L"Failed: ModifyRecipients", L"SendSMSMessage", MB_OK);<br />WriteString( L"Failed: ModifyRecipients - SendSMSMessage" );<br />return hr;<br />}<br />WriteString( L"Passed: ModifyRecipients - SendSMSMessage" );<br />// now we set the additional properties for the<br />// message<br />SPropValue props[4];<br />//note how we zero out the contents of the<br />// structure as MAPI is sensative to the<br />// contents of other fields we do not use.<br />ZeroMemory(&props, sizeof(props));<br />// first set the subject of the message<br />// as the sms we are going to send<br />props[0].ulPropTag = PR_SUBJECT;<br />props[0].Value.lpszW = (LPWSTR)lpszMessage;<br />// next set the senders email address to<br />// the phone number of the person we are<br />// sending the message to<br />props[1].ulPropTag = PR_SENDER_EMAIL_ADDRESS;<br />props[1].Value.lpszW = (LPWSTR)lpszFrom;<br />// finally and most importantly tell mapi<br />// this is a sms message in need of delivery<br />props[2].ulPropTag = PR_MSG_STATUS;<br />props[2].Value.ul = MSGSTATUS_RECTYPE_SMS;<br /> props[3].ulPropTag = PR_MESSAGE_FLAGS;<br /> props[3].Value.ul = MSGFLAG_FROMME | MSGFLAG_UNSENT;<br />hr = pMessage->SetProps(sizeof(props) / sizeof(props[0]), (LPSPropValue)&props, NULL);<br />if (FAILED(hr))<br />{<br />//MessageBox(NULL, L"Failed: SetProps", L"SendSMSMessage", MB_OK);<br />WriteString( L"Failed: SetProps - SendSMSMessage" );<br />return hr;<br />}<br />WriteString( L"Passed: SetProps - SendSMSMessage" );<br />// having set all the required fields we can now<br />// pass the message over to the msgstore transport<br />// to be delivered.<br />hr = pMessage->SubmitMessage(0);<br />if (FAILED(hr))<br />{<br />//MessageBox(NULL, L"Failed: SubmitMessage", L"SendSMSMessage", MB_OK);<br />WriteString( L"Failed: SubmitMessage - SendSMSMessage" );<br />return hr;<br />}<br />WriteString( L"Passed: SubmitMessage - SendSMSMessage" );<br />return S_OK;<br />}<br />/////////////////////////////////////////////////////////////////////////<br />// This is the function that creates the session, using the<br />// from, the recipient and the message.<br />// This opens the session, opens the sms message store and opens<br />// the drafts folder then create a new message and sets the sender,<br />// recipient and messag, then finally sends the message.<br />BOOL DoSendMessage(LPCTSTR lpszFrom, LPCTSTR lpszTo, LPCTSTR lpszMessage)<br />{<br />HRESULT hr = MAPIInitialize(NULL);<br />if (FAILED(hr))<br />{<br />//MessageBox(NULL, L"Failed: MAPIInitialize", L"DoSendMessage", MB_OK);<br />WriteString( L"Failed: MAPIInitialize - DoSendMessage" );<br />return hr;<br />}<br />WriteString( L"Passed: MAPIInitialize - DoSendMessage" );<br />// Initialized the MAPI subsystem<br />// CComPtr<IMAPISession> spSession;<br />ICEMAPISession * pSession = NULL;<br />BOOL bRet = FALSE;<br />hr = MAPILogonEx(0 ,NULL, NULL, 0, (LPMAPISESSION *)&pSession);<br />if (FAILED(hr))<br />{<br />//MessageBox(NULL, L"Failed: MAPILogonEx", L"DoSendMessage", MB_OK);<br />WriteString( L"Failed: MAPILogonEx - DoSendMessage" );<br />}<br />else<br />{<br />WriteString( L"Passed: MAPILogonEx - DoSendMessage" );<br />bRet = SUCCEEDED(SendSMSMessage(pSession, lpszFrom, lpszTo, lpszMessage));<br />if( bRet )<br />WriteString( L"Passed: SendSMSMessage - DoSendMessage" );<br />else<br />WriteString( L"Failed: SendSMSMessage - DoSendMessage" );<br />pSession->Logoff(0, 0, 0);<br />pSession->Release();<br />}<br />MAPIUninitialize();<br />return bRet;<br />}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.