I’m on a roll with blog posts today.
I just downloaded the TextFree SMS messaging app from the iTunes app store. I have an iPod Touch (or iTouch for short) and I wanted to get text messages on it to test a messaging system I’m building for the puzzle race (see Auto Email Responder). The app works well and if you don’t mind the advertising on it and the popups telling you to tell your friends about the app, it’s free. It even comes with a phone number where people can send you text messages.
I did some code work last night on the email program, now called autoemail, and it’s working well. I have been trying to keep things simple which has resulted in a few compromises worth mentioning. The program is built around am XML configuration file and a bunch of built-in responses defined in the file.
<autoemail> <servers> <smtp server="smtp.1and1.com" port="587" user="******" pass="******"/> <pop3 server="pop.1and1.com" port="110" user="******" pass="******"/> </servers> <responses> <response keyword="glubglub" answer="code"> Respone from glubglub because you sent "code". </response> <response keyword="glubglub" answer="*"> Your glubglub answer is wrong! Sorry. </response> <response keyword="hidden" answer="moo"> Look for the hidden puzzle near a large mooooo. </response> <response keyword="hidden" answer="*"> That is not the correct "hidden" answer. </response> <response keyword="getlogfile" answer="xyz" action="forward"> The log file cannot be sent at this time. </response> <response keyword="help" answer="*" action="forward"> Text help is not available. Please call for voice help or find one of the staff members to get help. </response> <response keyword="register" answer="***" action="register"> You have been registered. You will receive broadcasts and hints at this number/address until you send a message with "unregister" as the content.. </response> <response keyword="unregister" answer="*" action="unregister"> You have been unregistered. You will no longer receive broadcasts or other messages. </response> <response keyword="broadcast" answer="*" action="broadcast"> Your message has been forwarded to all registered senders. </response> <response keyword="*" answer="*"> Your message was not understood. </response> </responses> <forwarding> <forward keyword="help">***@*****.***</forward> <forward keyword="getlogfile">***@*****.***</forward> </forwarding> <livelog>*******@*****.***</livelog> </autoemail>
Example Configuration File
Above is the configuration file. Some of the text has been changed so that I’m not publishing my email addresses here.
The compromises are all related to the logging of information and flexibility of the program. They are not big compromises and only affect administration of the program, not what the end-user will see. Some description of the overall functionality, similar to what I posted in an older blog post, is in order. I’ll try to provide a bit more detail this time:
The program is written in C++ using MFC for Windows. I’ve moved all of the actual message handling code out of the Windowing code but I am still tied to MFC because of CString and CFile classes. This code could be ported in a very short time with little real effort but I have no reason to do so.
The Handler object is created when the program starts and it is then told, through a call to a StartHandler() function, to create a separate thread that will loop continuously and will get and send emails as needed.
There is no actual SMS text messaging being handled in this program. All of the message handling in done through an email server. When a user want to use the service, they send a text message to the proper email address and my program gets the email a few moments after it arrives on the server. When I send response emails, they are converted to SMS text messages, or text messages appropriate to whatever system is being used, by the server that is receiving the email. If I send an email to firstname.lastname@example.org then the AT&T server knows to forward that email to the phone number in the email address.
Within my message handling loop, the code first checks for configuration file changes. it then check for new email and if any are available from the POP3 server, they are retrieved one at a time and handled one at a time. Handling them involves one or two steps. The first step is to read through the Responses data in the configuration file. A response should always be found since the code uses wildcards in the file and will match whatever is sent to the last response. I will note here that the content of a message are only expected to be a keyword and an answer. If the user sends a message of “23” to “email@example.com” then my code will parse “23” as the answer and “dragons” as the keyword. Of course I can also handle a few other variations like the user sending “23 to dragons” to “?@myemailserver.com” or even to “X@myemailserver.com”. I do this so that people who can’t type fast don’t need to retype the server name for each message they send. They can just select it from the contacts list. This also allows them the potion of having all of their communications with my system be in a single text message conversation.
Back to the message handling. Once a response is found, the code check to see if a special action is available. These are hard-coded features of the program. Right now, special actions are available to:
- Register to get broadcast messages.
- Unregister from getting broadcast messages.
- Broadcast a message (if the right password is supplied).
- Forward the message to a known forwarding address.
- Send the log file to an known email address.
The forwarding of a help message was a recent addition and will allow a user to ask for help and for me or someone else getting the forwarded message to respond as if we are the server. For regular responses, everything is automatic.
The code also forwards every log file entry, when it is made, to a known forwarding address. This will let me track answers and possibly take off points when a user enters the wrong answer. I certainly don’t want someone solving a puzzle to send in 20 messages with 20 different numeric answers in the hopes of getting one right without also losing points for doing so.
The special actions are handled by functions in the handler and they do just what the descriptions say they do.
That’s it. The program does nothing else besides parsing incoming messages and sending responses, with the occasional special action. The code is small and simple and text parsing was the most difficult thing to write, aside from the email client code that I already had written and working before this project.