Message Destinations
Undoubtedly, messaging wouldn't be complete without destinations. Since the essence of messaging is to deliver information to persons, adding message destinations is an important part of the messaging procedures. In this section, we will thoroughly dissect various ways of adding message destinations.
Some aspects of adding message destinations apply only to Text Messaging (SMS and USSD) and will therefore not be covered here. A further look will be covered when dealing with Personalised Messaging. This section deals with the aspects that apply to both Text and Voice messaging.
Adding Destinations - So Far
In all sample codes considered so far where we have added message destinations, we
simply added phone numbers with the basic call to addDestination()
method.
In VB/VBA, addDestinationEx()
was rather called. A review will be beneficial:
// initialise message object
SMSRequest request = new SMSRequest();
// set message properties
request.setMessage("A test message!");
request.setSender("TEST");
request.setSMSType(SMSType.GSM_DEFAULT);
// add message destinations
request.addDestination("0242053072"); // local number format
request.addDestination("233246314915"); // international number format
One thing that can be observed is that the phone number to the first call of addDestination()
or addDestinationEx()
is provided in local number format whiles the phone number to the second call is in
international number format. Additionally, we do not know whether the phone numbers were actually added
to the destinations list or not. We will now delve more into these.
Phone Number Formats
When adding message destinations, phone numbers can be specified in either local or international number format. There are some few things to be noted on the formats when adding message destinations.
International Number Format
In messaging to mobile devices, phone numbers need to be specified in international number format which uniquely identifies the destinations globally. It is a combination of the country calling (dial) code and the local phone number. Here, we refer to local phone number to include area code.
As an example, consider sending a message to the phone number 0241999999 in Ghana.
Since Ghana's country calling (dial) code is +233
, we precede the phone number
with the international number prefix +233
. However, the leading zero in the local
phone number will have to be removed when concatenating number prefix and
the local phone number. Thus +233
and 241999999
will be concatenated
and the result will be +233241999999
. This can be set in code as follows:
The leading +
sign can be ignored and the phone number will still be added to the
message destinations list.
Local Number Format
Sometimes, phone numbers may exist in records in local number format. That is, without the leading country number prefix (dial code). In such cases, there will be no need to explicitly format all local phone numbers in international number format. This is automatically done before submitting messages.
By default, the country number prefix is initially picked from the user's account settings and used for concatenation with phone numbers in local number format. This, however, can be changed during code execution. Changes to the number prefix to be used for concatenation during execution are not applied to user account settings. We will look at this shortly.
The local phone number 0241999999
can be added to the destinations list simply by passing
it to addDestination()
or addDestinationEx()
method without worrying about formatting
in international number format.
As the leading +
could be ignored in the case of international number format,
the leading 0
can also be ignored in the case of local number format:
This is particularly helpful where phone numbers have been entered in a spreadsheet application,
particularly Microsoft Excel application, and the leading 0
has been stripped off. In such
cases, there is no need to explicitly precede phone numbers with leading zero. Local phone numbers
can still be added even without the leading 0
(zero).
Formatting in International Format
As earlier emphasised, phone numbers in local number format are by default automatically formatted in international number format by preceding the phone numbers with the number prefix for the country specified as the default destination country in user's account settings. However, during code execution, the number prefix for preceding local phone numbers can be changed only for formatting.
In the previous example, If the user's default destination country in account settings is Ghana (+233
), then the local
phone number 0241999999
will automatically be formatted as 233241999999
. But what if we want to add
other phone numbers for which destination is Nigeria but the phone numbers are in local number format? This is
simply accomplished by changing the default number prefix to be used for concatenation. We consider it next.
Default Number Prefix
The essence of the default number prefix is to be used in formatting phone numbers in international number format. This is done by preceding local phone numbers with the country's international number prefix. The default number prefix can be changed during code excecution.
From the following sample code, we assume that the default messaging country is Ghana. Hence the default
number prefix is +233
.
// add message destinations.
request.addDestination("233241234567"); // already in international number format.
// add phone number in local number format. In this case
// phone number will be formatted into 233241234567 since
// the default number prefix is +233
request.addDestination("0241234567"); // format into 233241234567
Now suppose we want to add another phone number in local number format for which the
destination is Nigeria but not Ghana. Also, suppose the phone number is 08012345678
.
If we add this phone number while the default number prefix is still set for Ghana (+233
),
it will be formatted in international number format as 2338012345678
. This is not what
we want because that will indicate a Ghanaian phone number.
To solve this problem, one way will be to change the default number prefix to that of Nigeria (+234
).
Another way to avoid this problem is to ensure that all phone numbers being added
are already in international number format.
// change default country calling code
request.setDefaultNumberPrefix("+234"); // country calling code for Nigeria
From this moment, any phone number in local number format that is added will automatically be
formatted in international number format using +234
.
It must be emphasised that changing the default number prefix this way does not effect the change in user's account settings. It is rather effected in application execution context for formatting phone numbers in international number format.
// add phone number
request.addDestination("0246123456"); // formatted as 233246123456;
// Add another phone number in local number format.
// Destination country is Nigeria so change the default number prefix
request.setDefaultNumberPrefix("+234");
// add phone number
request.addDestination("08012345678"); // formatted as 2348012345678
If there is the need to know the default number prefix that is currently set, a
call to getDefaultNumberPrefix()
must be made. If pre-initialisation has not been
made with AuthRequest
, this method will return null
.
Warning
Do not explicitly set a default number prefix when initial authentication has not been done
with AuthRequest
. If a call to setDefaultNumberPrefix()
is made whiles
pre-initialisation has not been done with AuthRequest
, then Exception
will be thrown.
Destinations From Text Stream
Phone numbers in text streams can easily be extracted and added to the destinations list. The text streams may be from file, database, or from user inputs. Sometimes, the streams of text may contain non-numeric data. Such cases should not call for alarm as there exists method to extract phone numbers irrespective of whether they are contained in non-numeric text data or not.
Extracting Phone Numbers
We can easily extract phone numbers contained in text streams for adding to the destinations list.
This is done by calling the static method extractPhoneNumbers()
of the phoneUtil
class in
the Utils
namespace. VB/VBA applications should rather call extractPhoneNumbersEx()
on an object of PhoneUtil
class. The method returns a list of phone numbers extracted from the specified
text stream.
To use extractPhoneNumbers()
method from the phoneUtil
class, the Utils
namespace may be imported.
It is not a requirement that text streams contain only phone numbers for extraction. Other text contents may exist in the stream but only values considered to be phone numbers will be extracted.
// Let's assume the following text stream from a file
string str = "Daniel, XYZ Avenue, 0242053072; Oppong, Box 45, 233201234567";
// extract the phone numbers into a list
ArrayList numbers = PhoneUtil.extractPhoneNumbers(str);
// now check and add extracted phone numbers.
if (numbers != null){
foreach (string num in numbers){
request.addDestination(num, false);
}
}
From the sample code, the text from which we extract the phone numbers contain non-numeric characters
as well. By passing this to extractPhoneNumbers()
or extractPhoneNumbersEx()
,
only phone numbers will be extracted and all non-numeric characters will be discarded.
Notice that in VB/VBA, extractPhoneNumbersEx()
is called on an object of PhoneUtil
class.
We will talk about the second argument to addDestination()
and why we set the value to false
shortly.
Adding From Text Stream
Sometimes, the phone numbers returned from the call to extractPhoneNumbers()
or extractPhoneNumbersEx()
may only be needed
for adding to the destinations list as was demonstrated earlier. If this is the case, then the extraction
and addition of the phone numbers to the destinations list can all be done simultaneously with a single
call to addDestinationsFromTextStream()
with an object of message request.
The method returns the count of phone numbers that passed validation and added to the destinations list.
// assume the following text stream from a file
string str = "Daniel, XYZ Avenue, 0241234567; Oppong, Box 45, 233201234567";
// extract and add phone numbers to the destinations list
int addedCount = request.addDestinationsFromTextStream(str);
// This not required. Just to know addedCount
Console.WriteLine("{0} phone numbers were added.", addedCount);
As seen, if the list of extracted phone numbers will not be needed for display but only for
adding to the destinations list, then a call to addDestinationsFromTextStream()
will do
both simultaneously. It will extract and add phone numbers from text streams into the destinations list.
Destination Validation
In all of our discussions to this point on adding message destinations, we have not considered validation of the phone numbers specified to be added to the destinations list. For instance, we do not check whether the phone numbers are accepted and added to the destinations list or not.
addDestination()
and addDestinationEx()
methods actually return a
NumberAddInfo
enumerator constant which indicates whether the destination was actually added or not. For phone numbers
that are not added, NumberAddInfo
enumerator constant that is returned indicates the reason for rejection.
If a destination is validated and added, the method returns NumberAddInfo.NAI_OK
.
// add phone number but we will check if it was added or not
if (request.addDestination("0241234567") == NumberAddInfo.NAI_OK){
Console.WriteLine("Hurray! Phone number was added.");
}
else {
Console.WriteLine("Oops! Phone number wasn't added.");
}
By default, if validation fails for a phone number to be added, Exception
will be thrown. A
value specified as phone number may fail validation if it is not considered to be a valid phone number
or when the user's route settings do not permit sending of messages to the country or network.
Exception Control
As indicated earlier, if validation fails for a destination specified to be added, then Exception
will
be thrown. The throwing of Exception
can be controlled when adding a message destination.
addDestination()
is overloaded to take other arguments. Similarly, addDestinationEx
takes
optional arguments. This second argument to addDestination()
or addDestinationEx()
is called
the Exception Control Specifier (ECS). To prevent the throwing of Exception when a phone number fails validation,
we pass false
as the second argument to addDestination()
or addDestinationEx()
.
By default, if the Exception Control Specifier (ECS) is not provided then it is considered to be true
.
In such case if the phone number fails validation, Exception
will be thrown.
// Exception should be thrown if phone number validation fails.
request.addDestination("233246123456");
request.addDestination("233246111111", true);
// If validation fails, don't throw Exception. Just ignore it.
request.addDestination("233246999999", false);
In this sample code, the ECS to the first call of addDestination()
or addDestinationEx()
is not set. By default, this will be considered as true
. Therefore if the phone number fails validation, Exception
will be thrown. Similarly with the second call, the ECS to addDestination()
or addDestinationEx()
is true
. This indicates that if validation fails, Exception should be thrown.
On the other hand, the third call to addDestination()
or addDestinationEx()
has the ECS set to false
.
This implies that if phone number validation fails, Exception should not be thrown but the
value should be ignored for code execution to flow. This is particularly handy when adding
phone numbers in an iteration (loop). We consider this next.
Adding Destinations In Iteration (Loop)
Sometimes, the need arises to add a lot of phone numbers to the destinations list. For instance, the phone numbers may be read from a database, file, or from user input. Adding a list of phone numbers requires iterating through the list of phone numbers in order to add them one at a time.
The simplest way to add message destinations from an array is to pass the collection of phone numbers
to addDestinationsFromCollection()
or addDestinationsFromCollectionEx()
. VB/VBA applications
must rather call addDestinationsFromCollectionEx()
to add message destinations
from an array.
In the sample code below, we create a collection of phone numbers directly in the code for demonstration purposes only. In production integration, the collection of phone numbers may be obtained from other source such as database, file, or user input.
// add destinations from a list
List<string> destsList = new List<string>();
destsList.Add("0241234567");
destsList.Add("0501234567");
// add list destinations
request.addDestinationsFromCollection(destsList);
// destinations array
string[] destsArr = new string[] {"0241234567", "0501234567"};
// add array destinations
request.addDestinationsFromCollection(destsArr);
Applications can also iterate through the collection of phone numbers to add the destinations by
calling addDestination()
or addDestinationEx()
methods.
When iterating through a list of phone numbers to be added, it may be convenient to set the ECS
for addDestination
or addDestinationEx()
to false
. This will imply that for a particular number to be
added, if the phone number fails validation, no Exception will be thrown. The value will only be ignored
and the next item in the list will be fetched. The benefit of this will be to prevent termination
of the iteration. However, if there is the need to ensure that no single item in the collection is left out, then
the ECS can be ignored or can be set to true
. Then, when phone number
validation fails for any single item in the list, the iteration will be terminated and Exception will be thrown.
The following sample code demonstrates when Exception may be thrown and when it will not.
// create a list of phone numbers for demonstration
string[] numbersList = new string[] {"0246123456", "233246999999", "233246888888"};
// add the phone numbers
// Throw Exception if any phone number fails validation
foreach (string number in numbersList)
request.addDestination(number);
// add phone numbers
// Throw Exception if any phone number fails validation
foreach (string number in numbersList)
request.addDestination(number, true);
// add phone numbers
// Do not throw Exception if any phone number fails validation
foreach (string number in numbersList)
request.addDestination(number, false);
// submit the message
MessageResponse resp = request.submit() as MessageResponse;
Warning
Do not place a call to submit()
of message request inside a loop that adds phone numbers.
The efficient way is to call submit()
outside of any iteration. Use iterations only for
adding multiple phone numbers to the destinations list.
This sample code shows three ways of adding phone numbers in an iteration. In the first iteration,
ECS for addDestination
or addDestinationEx()
is not set. Since the default is true
, the iteration
will be terminated and Exception thrown if any phone number fails validation.
In the second iteration, ECS is true
implying that if any phone number fails validation,
the iteration should be terminated and Exception should be thrown.
Lastly in the third iteration, the ECS is false
.
This means that if any of the phone numbers fail validation,
Exception must not be thrown. The phone number will only be ignored
and the iteration will not terminate but rather the next phone number in the list will be fetched.
An important thing that must be observed is that submit()
is called outside the loop. This ensures that
the destinations list is built on the client side before sending all in bulk to the server. If the call to
submit()
is placed inside the loop, each destination will be sent to the server individually before
fetching the next. This is very inefficient and must be avoided as it will take a long to time complete if
there are a lot of destinations.
Note
If you are calling submit()
on a message request inside a loop, then you
are doing it the wrong way. The ideal way is to build the destinations list in a
loop and then call submit()
outside the loop. This is so even in the case of
customising messages for each destinations which is discussed in the section on
Personalised Messaging.
Destination Identifiers
When messages are submitted, the messaging server automatically assigns unique identifier to each added destination and returns this identifier. The purpose for this is to be able to reference the destination later particularly when notifying or requesting delivery status of the destinations.
It is however possible for client applications to generate their own identifiers for each
destination to be added. Once generated, it can be passed to addDestination
and the unique identifier will be assigned to the destination on the server.
VB/VB
applications must however call addDestinationWithId
when adding destinations with custom generated unique identifiers to a destination.
A custom destination identifier can contain numeric only characters or alpha-numeric characters
with optional hyphens (-
). It must have a minimum of 30 characters and a maximum
of 40 characters. Additionally, destination identifiers must be unique for destinations in a message batch.
// add phone number with custom identifier
request.addDestination("0246123456", true, "b3115ee-4cf5-40b0-bcfe-3ea9f346e118");
After assigning a valid unique identifier to a destination in your application, the same identifier will be assigned to the destination as message identifier on the server. This means that you can reference the destinations with your custom unique identifiers that you generated in your application when there is the need to query delivery status of the destinations.
In VB/VBA, addDestinationWithId
was called to assign the unique identifier to the destination.
Unlike addDestination
which was called in the other programming languages, addDestinationWithId
in VB/VBA has a different order of arguments to the method call. In the call to addDestination
, the
unique identifier was set as the third argument with the second argument as the Exception Control Specifier (ECS).
However, in the call to addDestinationWithId
for VB/VBA, the unique destination identifier is set as
the second argument while the ECS is set as the third argument.
Recall our discussion on Exception Control. We indicated that ECS is optional and defaults
to true
. With this in mind, we can ignore ECS in the call to addDestination
and addDestinationWithId
when assigning custom unique destination identifiers. However, the ECS must always be specified in PHP integration
when assigning custom unique destination identifiers.
// add phone number with custom identifier
request.addDestination("0246123456", "b3115ee-4cf5-40b0-bcfe-3ea9f346e118");
Remember that ECS defaults to true
and so if destination validation fails, Exception
will
be thrown. To prevent throwing of Exception
when destination validation fails, ECS must be set to false
.
Checking Destination Existence
If there is the need to check if a phone number has been added to the destinations list,
then a call to destinationExists()
will do exactly that. The phone number to be checked
must be passed as argument to this method. The phone number can be in international or local number format.
// check to see if phone number exists in destinations list
if (request.destinationExists("233246123456")){
Console.WriteLine("Hurray! The phone number has already been added.");
}
else {
Console.WriteLine("Oops! The phone number has not been added yet.");
}
destinationExists()
returns true
if the phone number exists in the destinations list
otherwise it returns false
.
Total Message Destinations
Sometimes the need arises to know the total number of destinations that has been added for a
particular message. To get total destinations, a call to getDestinationsCount()
has to be made.
// get total destinations
int destsCount = request.getDestinationsCount();
Updating Destination
A message destination is added as a phone number to which the message will be delivered. If for any reason the need arises to change the phone number, it can easily be done either by specifying the previous phone number or an assigned unique destination identifier whiles whiles also specifying the new phone number to be set.
Updating Destination by Phone Number
To update a message destination phone number, we will need to call updateDestination(String, String) with the existing phone number to be updated as the first argument whiles specifying the new phone number as the second argument.
// get total destinations
request.updateDestination("233241234567", "233201999999");
From the sample code, if the destinations list contains the phone number 233241234567
,
then it will be updated to 233201999999
and the method will return true
. However,
if the phone number is not found, Exception
will be thrown.
Updating Destination by Unique Identifier
Phone numbers for message destinations with unique identifiers assigned can be updated by calling updateDestinationById(String, String) and passing the destination unique identifier as the first argument with the new phone number as the second argument.
// get total destinations
request.updateDestinationById("b3115ee-4cf5-40b0-bcfe-3ea9f346e118", "233201999999");
If the destinations list has a destination with the specified unique identifier, then it's associated phone number will be changed to the phone number specified as the second argument to the method call. If the unique identifier is not found, then Exception will be thrown.
Removing Destination
Just as destinations are added to a message for submission, they can also be removed from the destinations list before submitting. Destinations can be removed either by specifying the phone number or by specifying an assigned unique destination identifier.
Removing Destination by Phone Number
A message destination can be removed by calling removeDestination(String) while specifying the phone number as the argument to the method call. The phone number can be specified in either international or local number format. If the specified destination exists, it will be removed.
A sample call is demonstrated as follows.
// remove destination
request.removeDestination("0246123456");
request.removeDestination("2348012345678");
Removing Destination By Unique Identifier
If unique identifiers have been assigned to message destinations, then those destinations can be removed by calling removeDestinationById(String) and passing the unique destination identifier as a parameter to the method call.
// remove destination using destination identifier
request.removeDestinationById("b3115ee-4cf5-40b0-bcfe-3ea9f346e118");
request.removeDestinationById("beeb22ee-d744-de79-cff6-11f3892637e8");
In both cases, the method call will return true
if the specified destination is found
and successfully removed, otherwise the return value will be false
.
Clearing Destinations
The destinations list may also be emptied by calling clearDestinations(). This will remove all phone numbers that have been added to the destinations list. The call may be necessary where the message request object needs to be reused after sending a message.
// remove all phone numbers in the destinations list
request.clearDestinations();
It must be emphasised that after sending a message, the destinations list is not emptied. Hence, to use the same message request object for sending another message, the previous destinations list should be emptied to prevent sending to those destinations again.