Send SMS

Radio Interface Layer Forum. This forum is related to ril api, sms api, telephony api, phone api and everything that works with the modem inside a mobile device.
Get caller ID, get tower cell info, cell id, intercept sms at ril level, all inside.

Moderator: Teksoft

Send SMS

Postby rain » Thu May 04, 2006 8:59 pm

How can i send an SMS programaticaly?
Ask the forum - we will answer your questions
rain
TEK-Newbie
TEK-Newbie
 
Posts: 3
Joined: Thu May 04, 2006 4:47 pm

Postby sad_ghost » Thu May 04, 2006 9:08 pm

There are two ways of doing this :
using SMS api as in the sample provided in the SDK (\Samples\Win32\Cellcore\Sms\HelloSMS)

or you can do something like this ( i used it on 2005 devices with some "problematic RUUs" on wich standard SMS API just didn't work)

#include "stdafx.h"
#include <cemapi.h>
#include <mapiutil.h>
#include "resource.h"

/////////////////////////////////////////////////////////////////////////////////////////////
// This function is used to get the msgstore named SMS from msgstores on the
// device.
// I could have used just raw pointers but it is much easier and safer to just
// use smart pointers.
HRESULT GetSMSMsgStore(const CComPtr<IMAPISession>& spSession, CComPtr<IMsgStore>& spMsgStore)
{
// first we get the msgstores table from the session
CComPtr<IMAPITable> spTable;
HRESULT hr = spSession->GetMsgStoresTable(MAPI_UNICODE, &spTable);
if (FAILED(hr))
{
return FALSE;
}

// next we loop over the message stores opening each msgstore and
// getting its name to see if the name matches SMS.
// If it does then we break out of the loop
while (TRUE)
{
SRowSet* pRowSet = NULL;
hr = spTable->QueryRows(1, 0, &pRowSet);

// If we failed to query the
// rows then we need to break
if (FAILED(hr))
{
break;
}

// if we got no rows back then just exit the loop
//remembering to set an error
if (pRowSet->cRows == 1)
{
ASSERT(pRowSet->aRow[0].lpProps->ulPropTag == PR_ENTRYID);
SBinary& blob = pRowSet->aRow[0].lpProps->Value.bin;
hr = spSession->OpenMsgStore(NULL, blob.cb, (LPENTRYID)blob.lpb, NULL, 0, &spMsgStore);
if (FAILED(hr))
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
}

// now remember to free the row set
FreeProws(pRowSet);
if (FAILED(hr))
{
break;
}

// now get the display name property from the
// message store to compare it against the name
// 'SMS'
SPropTagArray props;
props.cValues = 1;
props.aulPropTag[0] = PR_DISPLAY_NAME;

ULONG cValues;
SPropValue* pProps = NULL;
hr = spMsgStore->GetProps(&props, MAPI_UNICODE, &cValues, &pProps);
if (FAILED(hr) || cValues != 1)
{
break;
}

// if the name matches SMS then break and as
// hr == S_OK the current MsgStore smart pointer
// will correctly be set.
if (_tcsicmp(pProps[0].Value.lpszW, _T("SMS")) == 0)
{
break;
}
}

// if we failed for some reason then we clear out
// the msgstore smartpointer and return the error.
if (FAILED(hr))
{
spMsgStore.Release();
}

return hr;
}


/////////////////////////////////////////////////////////////////////////////////////////////
// This function is used to get the folder named drafts from the msgstore on the
// device.
// I could have used just raw pointers but it is much easier and safer to just
// use smart pointers.
HRESULT GetSMSFolder(const CComPtr<IMsgStore>& spMsgStore, CComPtr<IMAPIFolder>& spFolder)
{
// Now get the Drafts folder.
SPropTagArray propDefaultFolder;
propDefaultFolder.cValues = 1;
propDefaultFolder.aulPropTag[0] = PR_CE_IPM_DRAFTS_ENTRYID;

ULONG cValues;
LPSPropValue pPropVals;
HRESULT hr = spMsgStore->GetProps (&propDefaultFolder, MAPI_UNICODE, &cValues, &pPropVals);
if (FAILED(hr))
{
return hr;
}

SBinary& eidDrafts = pPropVals->Value.bin;

hr = spMsgStore->OpenEntry(eidDrafts.cb, (LPENTRYID)eidDrafts.lpb, NULL, MAPI_MODIFY, NULL, (LPUNKNOWN*)&spFolder);
if (FAILED(hr))
{
}

return hr;
}

/////////////////////////////////////////////////////////////////////////////////////////////
// This function is used to get the send the message.
// This uses an opened MAPI session
HRESULT SendSMSMessage(const CComPtr<IMAPISession>& spSession, LPCTSTR lpszFrom, LPCTSTR lpszTo, LPCTSTR lpszMessage)
{

// now get the SMS message store
CComPtr<IMsgStore> spMsgStore;
HRESULT hr = GetSMSMsgStore(spSession, spMsgStore);
if (FAILED(hr))
{
return hr;
}

CComPtr<IMAPIFolder> spFolder;

hr = GetSMSFolder(spMsgStore, spFolder);
if (FAILED(hr))
{
return hr;
}

CComPtr<IMessage> spMessage;
hr = spFolder->CreateMessage(NULL, 0 ,&spMessage);
if (FAILED(hr))
{
return hr;
}

// set the recipients
// set up the required fields for a recipient
SPropValue propRecipient[3];
// it is vital we clear the property structure
// as there are fields we do not use but MAPI seems
// to be sentative to them.
ZeroMemory(&propRecipient, sizeof(propRecipient));
// set the recipient type which coul be to, cc, bcc
// but ehre must at least be a to field
propRecipient[0].ulPropTag = PR_RECIPIENT_TYPE;
propRecipient[0].Value.l = MAPI_TO;

// we set the type of address to sms instead of
// smtp
propRecipient[1].ulPropTag = PR_ADDRTYPE;
propRecipient[1].Value.lpszW = _T("SMS");
// we finally set the email address to the
// phone number of the person we are sending the message
// to
propRecipient[2].ulPropTag = PR_EMAIL_ADDRESS;
propRecipient[2].Value.lpszW = (LPWSTR)lpszTo;

// set the addrlist to point to the 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);

if (FAILED(hr))
{
return hr;
}
else
; // added the recipient to the message

// now we set the additional properties for the
// message
SPropValue props[4];

//note how we zero out the contents of the
// structure as MAPI is sensative to the
// contents of other fields we do not use.
ZeroMemory(&props, sizeof(props));

// first set the subject of the message
// as the sms we are going to send
props[0].ulPropTag = PR_SUBJECT;
props[0].Value.lpszW = (LPWSTR)lpszMessage;

// next set the senders email address to
// the phone number of the person we are
// sending the message to
props[1].ulPropTag = PR_SENDER_EMAIL_ADDRESS;
props[1].Value.lpszW = (LPWSTR)lpszFrom;

// finally and most importantly tell mapi
// this is a sms message in need of delivery
props[2].ulPropTag = PR_MSG_STATUS;
props[2].Value.ul = MSGSTATUS_RECTYPE_SMS;

props[3].ulPropTag = PR_MESSAGE_FLAGS;
props[3].Value.ul = MSGFLAG_FROMME | MSGFLAG_UNSENT;

hr = spMessage->SetProps(sizeof(props) / sizeof(props[0]), (LPSPropValue)&props, NULL);
if (FAILED(hr))
{
return hr;
}

// having set all the required fields we can now
// pass the message over to the msgstore transport
// to be delivered.
hr = spMessage->SubmitMessage(0);
if (FAILED(hr))
{
return hr;
}

return FALSE;
}

/////////////////////////////////////////////////////////////////////////
// This is the function that creates the session, using the
// from, the recipient and the message.
// This opens the session, opens the sms message store and opens
// the drafts folder then create a new message and sets the sender,
// recipient and messag, then finally sends the message.
BOOL DoSendMessage(LPCTSTR lpszFrom, LPCTSTR lpszTo, LPCTSTR lpszMessage)
{

HRESULT hr = MAPIInitialize(NULL);
if (FAILED(hr))
{
return hr;
}
else
; // initialized the MAPI subsystem

CComPtr<IMAPISession> spSession;

BOOL bRet = FALSE;

hr = MAPILogonEx(0 ,NULL, NULL, 0, &spSession);
if (FAILED(hr))
{

}
else
{
bRet = SUCCEEDED(SendSMSMessage(spSession, lpszFrom, lpszTo, lpszMessage));

spSession->Logoff(0, 0, 0);

spSession.Release();
}

MAPIUninitialize();

return bRet;
}

You can call it like this
DoSendMessage(m_strFrom, m_strTo, m_strMessage);
DoSendMessage(_T("SMS"), _T("0742010027"), _T("We are here to answer your questions"));
sad_ghost
TEK-Giant
TEK-Giant
 
Posts: 269
Joined: Thu Apr 06, 2006 11:04 am

Re:

Postby radhoo » Fri May 05, 2006 7:20 pm

Will the genie in the magic bottle grant me 3 wishes if i send an SMS to that number? :)
radhoo
TEK-Insider
TEK-Insider
 
Posts: 640
Joined: Fri Mar 17, 2006 2:47 am

Postby Carty » Thu Jun 01, 2006 12:07 pm

Hello,

Im a novice developer and know only VB.net

I downloaded a sample from msdn to send sms. They have writen a class named sms and using that as namespace, i use the code sms.sendmessage (number,message).Hope you would have seen the sample already. Now what i need is, this sends sms in class0. But i want them to be sent as class1 sms. Can you help me please,

Thanx a million in advance.

Regards
Carty..
Try to get the best out of you, that would be the key to Success - NiCK Carty..
Carty
TEK-Seeker
 
Posts: 18
Joined: Thu Jun 01, 2006 11:46 am
Location: India

hello

Postby radhoo » Thu Jun 01, 2006 12:27 pm

Dear Carty,

As you are saying, if you are at the begining of your developer career, you are free to choose your tools.

For a beginner everything will be hard, both VB.net and VC++ so why not choosing VC++?

The idea is that as you have said, from time to time you need to modify a flag or a tiny aspect that the already-done classes that you are using cannot support, and then you are lost. But if you control everything (and you can do this from vc++), you are free to set everything as you like.
So I very warmly suggest to choose the vc++ path, at least for mobile devices is better (you wont have everything you need with VB.net, as almost everytime you will have to load third party .dll-s and so and that's not an option).

Back to your question:
Do you have the source code of that class?

// PS_MESSAGE_CLASS0 - flash msg, no storage
// PS_MESSAGE_CLASS1 - msg with storage
txtProviderData.psMessageClass = PS_MESSAGE_CLASS1;
txtProviderData.psReplaceOption = PSRO_NONE;
dwProviderLength = sizeof(TEXT_PROVIDER_SPECIFIC_DATA);
// Send the message
hr = SmsSendMessage(hSms, NULL, &smsDestination, NULL,
(BYTE *)tchMessage, dwMessageLength, (LPBYTE)&txtProviderData,
dwProviderLength, SMSDE_OPTIMAL, SMS_OPTION_DELIVERY_NONE,
&smsMsgId);

You need to look for the call to the SmsSendMessage, and for the 7th parameter (as above, txtProviderData) to change the .psMessageClass to PS_MESSAGE_CLASS0 so you can "flash" your sms.


Regards,
Radu
radhoo
TEK-Insider
TEK-Insider
 
Posts: 640
Joined: Fri Mar 17, 2006 2:47 am

Postby Carty » Fri Jun 02, 2006 9:12 am

Thanx for the quick reply. This site gonna turn out a best one for pocket pc supports.

Well C# is ultimate but damn complicated i feel. VB.net is just too cool and easy i feel!

And, here is the sample im talking about.

Can you please download the VB.net version listed there. You can see a sms class used in it. It sends class0 sms but i want class1. Can you help me please.

I would much appreciate if you could edit it and send me :)

Thanx a million.

Regards
Carty..
Try to get the best out of you, that would be the key to Success - NiCK Carty..
Carty
TEK-Seeker
 
Posts: 18
Joined: Thu Jun 01, 2006 11:46 am
Location: India

re:

Postby radhoo » Fri Jun 02, 2006 11:07 am

Well C# is ultimate but damn complicated i feel. VB.net is just too cool and easy i feel!

Not C# Carty, i said C++. C# is as useless as VB is.

Ok Carty, sooner or later you'll have to get to C++ :lol:

Lets apple that sample you gave me the link to.
We don't care to place any options on the provider data structure, so we allocate space for its representative structure and keep its fields blank.

Byte[] ProvData = new Byte[12];


Well we need to 'care' about this one and change it a bit.

this ProvData corresponds to the API TEXT_PROVIDER_SPECIFIC_DATA structure, but its incorrectly defined, must be new Byte[164] (this is the correct size for the TEXT_PROVIDER_SPECIFIC_DATA).

Now we need to setup the psMessageClass field of TEXT_PROVIDER_SPECIFIC_DATA to PS_MESSAGE_CLASS1 (PS_MESSAGE_CLASS1=1).

The offset for psMessageClass is 4.

so do this:

Byte[] ProvData = new Byte[164];

and assuming that in VB arrays start from position 0 (i dont use VB...)

do ProvData[4] = 1;


(in case arrays start from 1, do ProvData[5] = 1).

Then you can call:

retVal = SmsSendMessage(smsHandle, 0, smsAddress, 0, smsMessage,
smsMessageTag.Length, ProvData, 164


notice the 8th parameter. its changed to 164 instead of 12 which is incorrect.



Hope this works for you, and dont forget C++ lets you see things much better :lol:


Radu
radhoo
TEK-Insider
TEK-Insider
 
Posts: 640
Joined: Fri Mar 17, 2006 2:47 am


Return to RIL

Who is online

Users browsing this forum: No registered users and 0 guests


cron