Topic:Implementing mail using CARAVAN.
-------------------------------------
Intro:
First a few things about internet mail.
Mail is mostly sent over the internet using SMTP protocol. As you can see from the format of the internet
mail address "user@domain.com", every email address is linked to a domain and there is a unique userid for
every mail user. Most of the time you can connect to the http or ftp servers using ftp.domain.com or www.domain.com
to access these services. But mail works differently and there is a more reliable way to find the mail host
using the DNS system. DNS information for a domain contains the mail host name in what is called the MX record.
When you access the MX record you will get the names of the SMTP servers that handle the domain's mail. Usually
there is more than one such SMTP server and the MX record has a number which indicates the order of
preference -- the lower this number the more preferable it is to send the mail to this host.
When you send a mail you do the following.
1. Lookup the DNS for the domain's MX record.
2. Make a list of mail hosts for this domain.
3. Send the mail using SMTP protocol to the most preferred mail host - trying the next if any problem.
To receive a mail you should:
Install an SMTP server and register it on the DNS.
In your domain's MX record enter the fully qualified hostname of your SMTP server.
Your ISP should be able to help you with this.
Now when ever you send the mail from a smtp client it will connect to your SMTP server and post the mail.
Caravan can both receive and send mail for a domain. To send mail it is sufficient to know the domain name
and the DNS address/es . DNS lookup is built into caravan for this purpose.
These can be set in the settings menu of caravan. Additionally most SMTPs do a reverse
lookup to check if you are the domain that you claim to be (atleast this is what I guess). So registering your IP address
on the DNS is probably important. If you want caravan to receive mail you should register the host on the internet
with something like mail.domain.com or anything with a valid IP address. Then change your domains MX record
so the it contains this hostname.
So much for setting up caravan to receive and send mail. But some things are still left.
Caravan is just an engine, it needs to be driven by some code.
Sending mail:
It is very simple to send mail from Caravan.
Caravan uses a object of type mail to send and receive mail.
You can create a mail object like this:
mail mymail;
Some properties of this object have to be set:
to: the recipient address
cc: cc recipient address.
subject: subject of mail
text: text of mail
attachment : attachments if any.
Some properties are set automatically.
from: sender's address
Since a user is identified when he/she is logged in, this information is filled in by caravan. Conversely if the
script is run in public domain (without login) mail cannot be sent.
An example for sending mail:
mail mymail
mymail(to)="kdv_@yahoo.com"
mymail(cc)="kdv@response4u.com"
mymail(subject)="This is a test for sending mail"
mymail(text)="hello\nblah .. blah\n"
mymail(attachment)=myfile(file)
The mail object is automatically queued ==== more about this after this.
An actual example from response4u:
if mx(type)="addnewuser"
mx(to)=users(email)
mx(subject)="Your registration accepted :"
mx(subject(01))+=users(agency)
mx(subject(01))+="(email:"
mx(subject(01))+=users(email)
mx(subject(01))+=")."
mx(text)="Your request for registration for the digital ad acceptance service has been accepted\r\n. Your login is:"
mx(text(01))+=users(login);
mx(text(01))+=". Please login with your login and password:\"password\"."
mx(text(01))+="\r\n"
sql(cords)=users(cords)
mx(text(01))+="Your have been assigned the following co-ordinators:\r\n"
loop ccl (sql(cords(00)))
if sql(cords(ccl(count)))<>"0"
users(recordno)=sql(cords(ccl(count)))
if users(recordno)=sql(cords(ccl(count)))
mx(text(01))+="\r\n"
mx(text(01))+=users(agency);
mx(text(01))+="-"
mx(text(01))+=users(city)
mx(text(01))+=": Tel:"
mx(text(01))+=users(phone);
mx(text(01))+=", email:"
mx(text(01))+=users(email);
mx(cc)=users(email)
endif
endif
repeat ccl 16
mx(text(01))+="\r\n\r\n"
mx(text(01))+="This is a computer generated message: Please do not reply to this email\r\nThank you.\r\n..... registration@response4u.com"
elseif;
// ....
endif
Queueing.
Q. why caravan has queues and eventhandlers in the first place?
Every caravan object is destroyed in the garbage collection phase after the execution is completed except for mail
and form objects. Mail objects which have not been sent successfully are automatically queued into the smtp queue
which is handled by a user defined eventhandler. Form objects are posted to their destination server in a separate
thread -- if there is lot of form generation or if more reliabilty is desired, forms can be put into any user
defined queue and will be handled sequentially by the designated eventhandler.
One can also explicitly post the mail by:
mymail(post);//In this case it will not go into queue if post was successfull.
The following code is used as the eventhandler for sending SMTP mail at response4u.
example : mailer.html
eventhandler(smtp) ;// declares this code as eventhandler for handing "smtp" queue
mail mx=_event(item);// gets the topmost item in queue
mx(post);// post it,
output con; // output to cosole
mx(error);// error info if any
_event(deleteItem);// deletes this item from queue.
// but the mail object mx will append to queue again
// if post was not successfull!
Programming caravan for receiving mail:
Now our server is listening on port 25 for any incoming mail. Still it does not know
whether to accept any particular mail and if accepted what to do with it.
SMTP protocol needs TWO hooks for receiving mail and these are written using caravan script.
The names of these files are fixed.
1. mailuser.html
Tells Caravan if it is ok to accept mail for a particular user or not.
This is done by setting the property accept
mail(accept)="ok";
if you have just this all mail will be accepted or you can have your on logic for this.
sample code from response4u:(mailuser.html)
(on responsee4u mail is accepted if the user exists)
append c:\adint\doc\mail.txt;// appends to this file for logging purpose
time t
"Got mail for user ";mail(recipient);" at ";t(dd);"-";t(mm);"-";t(yy);" ";t(hour);":";t(minute);// logs the time etc
var mailto={mail(recipient)}X{"`*`\@`*`"}:{userid,domain};// a caravan parser at work
// splits email address to userid and domain
if mailto; // mailto is created if the email was in format
user x; // instance of user
x(userid)=mailto(userid); // set userid
if x(uid); // check if it return valid numeric id
if x(uid)<>"0"; // there is non zero id for this user
mail(accept)="ok"; // ok to accept
"-- Accepted"; // logs this as accepted
endif
endif
endif
"\r\n"; // add a linefeed to our log
2. mailaction.html
An object of type mail is passed to this script. This is the received mail with
all the attendant properties set. You may do what you wish with it.
additional properties of recieved mail:
recipient: (list of all all recipients of this mail)
received: smtp headers which contains the text appended by the routing smtps
The recipient property has as many values as there are recipients for this mail.
Logic for mailaction.html:
Loop through all the recipients and parse each name to get the userid and domain.
If it is for our domain, insert the contents of this mail including the text, attachments, header,
current time etc into separate fields of our mail table. Additional information like userid is also
useful so that an sql query can be used get the users mail, when implementing a web based mail
client. Such a facility is implemented on response4u. To avoid confusion I am not attaching this
code here because other concepts of caravan language needs to be explained before one
can understand this code.