使用 CEMAPI 发送 SMS
如何使用 CEMAPI API 发送 SMS。
引言
如果您没有 Pocket PC Phone Edition 或 Windows CE SmartPhone 设备,那么很抱歉,本文对您没有用处。
现在,说清楚了,本文将展示如何使用 Windows CE MAPI API (也称为 CEMAPI) 而不是提供的 SMS API 向另一个支持 SMS 的设备发送 SMS。
背景
SMS 或简单消息服务是一种通过 GSM 网络向另一个支持 SMS 的设备发送短消息(最多 160 个字符)的方式。在 Pocket PC Phone Edition 设备和 Windows CE Smart 手机上,选择文件夹时,至少应该有一个 ActiveSync 和 SMS 消息存储,并且可能还有一个 MMS 消息存储。
这些消息存储将来自不同传输提供商的消息本地存储在设备上。
就本文而言,我们将专注于 SMS 消息存储,因为我们要使用它来发送消息。
使用代码
为了使代码更简单易懂,大部分代码使用 MFC 进行用户界面编程,并使用 ATL 来支持智能指针。
如果有人要求,我可能会提供一个仅 Win32 版本,因为相关代码(即,非 UI 代码)只需要 ATL 而不需要 MFC。
在本文中,我不会详细介绍 MAPI 会话的创建以及 SMS 消息存储和发件箱文件夹的打开过程。代码注释良好,并在源代码 zip 文件中的两个函数 GetSMSMsgStore
和 GetSMSFolder
中提供,这两个函数分别获取相关的 SMS 消息存储和 SMS 草稿文件夹。
因此,我们从在发件箱文件夹中创建新消息时开始查看代码。
大部分代码涉及创建收件人以及设置发件人和消息状态。
首先是设置消息的收件人。为了使代码更清晰,我只为一个消息设置了一个收件人,尽管可以设置多个收件人,每个收件人都需要三个属性,收件人类型、地址类型和电子邮件地址。
不幸的是,我发现 Microsoft 为 MAPI 示例提供的代码过于复杂,因为它们被过于复杂的内存和指针操作所掩盖。为此,我为收件人提供了一个更简单的实现。
首先,我们创建收件人所需的属性。
SPropValue propRecipient[3]; ZeroMemory(&propRecipient, sizeof(propRecipient)); // set the recipient type which coul be to, cc, bcc // but there must at least be a to field then the propRecipient[0].ulPropTag = PR_RECIPIENT_TYPE; propRecipient[0].Value.l = MAPI_TO; propRecipient[1].ulPropTag = PR_ADDRTYPE; propRecipient[1].Value.lpszW = _T("SMS"); propRecipient[2].ulPropTag = PR_EMAIL_ADDRESS; propRecipient[2].Value.lpszW = (LPWSTR)lpszTo;
如果要向消息添加其他收件人,可以将 propRecipient
扩展为三的倍数,并添加相应的收件人类型、地址类型和地址属性。
接下来,需要使用指向收件人属性的指针和属性计数来设置 ADRLIST
结构。您需要为每个收件人提供一个 ADRENTRY
。
// we create the addlist structure and set it to point to the recipient // properties ADRLIST adrlist; adrlist.cEntries = 1; adrlist.aEntries[0].cValues = 3; adrlist.aEntries[0].rgPropVals = (LPSPropValue)(&propRecipient); // finally modify the recipients of the message hr = spMessage->ModifyRecipients(MODRECIP_ADD, &adrlist);
最后,我们将消息的主题设置为要发送的 SMS 正文的文本。请注意,SMS 消息的长度不能超过 160 个字符,因为这是使用 GSM 短消息服务可以发送的消息的最大大小。
最后,我们设置其余属性,即发件人作为消息的发起人,以及消息记录类型为 SMS,以便它被传输层枚举并正确发送。可选地,消息可以设置消息标志,表明该消息未发送并且来自我。
SPropValue props[4]; ZeroMemory(&props, sizeof(props)); // set the subject props[0].ulPropTag = PR_SUBJECT; props[0].Value.lpszW = (LPWSTR)lpszMessage; //Set the sender props[1].ulPropTag = PR_SENDER_EMAIL_ADDRESS; props[1].Value.lpszW = (LPWSTR)lpszFrom; //Set the message status to indicate this message needs //enumeration. Vital property! props[2].ulPropTag = PR_MSG_STATUS; props[2].Value.ul = MSGSTATUS_RECTYPE_SMS; // Optional flags property for the message flags // Seems to work okay without these being set props[3].ulPropTag = PR_MESSAGE_FLAGS; props[3].Value.ul = MSGFLAG_FROMME | MSGFLAG_UNSENT; // Finally set the properties on the message hr = spMessage->SetProps(sizeof(props) / sizeof(props[0]), (LPSPropValue)&props, NULL);
由于消息上已设置了所有属性和收件人,因此可以安全地调用 SubmitMessage
。
//Submit the new message to the message store so that it may be submitted to the appropriate message transport provider. hr = spMessage->SubmitMessage(0);
如果您等待几秒钟,该消息将出现在您在消息的“收件人”字段中指定的电话号码上。另请注意,已发送的消息现在将出现在“已发送邮件”文件夹中,正如您所期望的那样。
我目前还没有在此处包含 Win32 或 SmartPhone 版本的代码。但是,如果有人想要它的版本,请给我发电子邮件,我会考虑更新示例以包括 SmartPhone 和纯 Win32 版本。
关注点
无
历史
到目前为止,没有修订。