CODECALL Programming Tutorials Linux Tutorials, Guides and Tips Sending Emails With Sendmail - Part 2 Started by, Aug 31 2009 04:55 PM form, Posted 31 August 2009-04:55 PM Ok, so now that you know how to use sendmail to send basic text emails, it's time to move on to something more interesting. Because sending HTML emails will inevitably require embedding images and other stuff, I'll teach you how to add attachments first. Let's say we're working on a project with our friend Bob, and we want to share some files with him, foo.c and readme.txt. But how... As I stated in my earlier tutorial, the purpose of the MIME headers is to indicate type information about what you're sending. Unfortunately there's no I-Am-An-Attachment header, but there are a few headers we can use in combination to get the desired effect. Take a look: Subject: Source Code Wait...what?! What happened to text/plain? Well, we need to tell the mail server that we're sending an email with more than one part, i.e. the message and some attachments. Because the server has no way of knowing how long each of the parts are, we pass the boundary argument. We will have to stick this in between every part of the message, on its own line, preceded by two dashes. The end of the message must have the boundary marker, but with two dashes at the end as well: blah blah part one blah blah part two blah blah last part... -- 1 of 5 12-11-02 02:49 PM
2 of 5 12-11-02 02:49 PM Your mail client (i.e. Gmail, Yahoo, etc.) will a much longer and more random boundary marker, like --smtp.yahoo.com--310820091952gmt-5--. Why? Well, imagine if one of the files I'm sending just happens to contain the text on a line by itself. Oops. The mail server is going to interpret that as the end of the file...and that'll screw everything else up. Better to have a ridiculous boundary that no one is going to read anyway than to have a simple one and run the risk of messing up the message. Wait, we're not done yet...immediately after each boundary marker (except the last one indicating the end of the message, of course) we have to declare the type of the part we're sending. In this case, it'll be text/plain for each of our parts since we're sending just plain text files. We also need to add a header declaring each part as either an attachment or part of the message text that Bob is going to read, like so: Message body: Content-Type: text/plain Attachment: Content-Type: text/plain Content-Disposition: attachment; filename="whatever.txt" Some text file containing unimportant stuff here.. Crap...sendmail might choke on that...we'll have to make sure to pass -i to avoid this problem. Notice that again, we have to leave a blank line to signal the end of the headers. Putting it all together, here's our final email: Subject: Source Code Content-Disposition: attachment; filename="foo.c" #include <stdio.h>
3 of 5 12-11-02 02:49 PM int main(void) { printf("\n"); return 0; } Content-Disposition: attachment; filename="readme.txt" This is a program that prints "" to the console and exits. -- I slipped in something extra--did you notice the charset=iso-8859-1 parameter? It tells the email client what character set to use to render the text. If I were sending text in Russian, for example, I could put UTF-8, which is one of the most widely supported Unicode formats. It's always good practice to put this parameter in, otherwise the client will use the user's preferred setting - and that can cause problems. Say someone in China decides to send me a text file. They may write it with the Latin alphabet, but since their default encoding is UTF-8 and mine is ISO 8859-1, I'm going to see a bunch of garbled symbols. So always specify your character set. Now, let's say we want to send Bob a different kind of file - a binary file. Say a.tar.gz. Clearly we're going to have problems here...binary doesn't transfer well because many systems truncate bytes to 7 bits. Why, I don't know. But - happily, we have a way around this, called base-64 encoding. By using only the characters 'a'-'z', 'A'-'Z', '0'-'9', '+', and '/' ('=' is used in special cases as well), you can encode anything. Think of it like hexadecimal, except base-64 and not base-16. Luckily, *NIX systems come with a utility to help us in our quest. First thing we need to do is encode our file: diarguet@rtp-lds-035:~$ cat myarchive.tar.gz uuencode -m /dev/stdout > myencodedarchive.base64 Ugly, I know, but for some reason I can't get it to work any other way. uuencode also has an annoying habit of sticking this begin base64... line at the beginning, so make sure to remove that first line before you put it in your email. If you open your file, you should get something frightening, like this: R0lGODlhEgATAJEAAAAAAP///wCZAP///yH5BAEAAAMALAAAAAASABMAAAIo ji+pgyk8ninquitfbvnfvheg1umhdzrqaawu6xzvjkb0/cyxo8joaqa7 ==== If I typed that right, it should be a little GIF image of a tree. Great! So now we've got our archive all nice and encoded...now what? Well, we need a MIME type for this. Er...well, we can look at the IANA list of all MIME types (http://www.iana.org/assignments/media-types/) and find the appropriate type with some work, or we can look at this list (http://www.webmaster-toolkit.com/mime-types.shtml) that lists MIME types by file extension. Note that it's not complete and some of the extensions may not be listed. For those that aren't, you'll have to make the judgment yourself. In this case, since we're using a.tar.gz file, we want application/x-compressed. So, off we go: Content-Type: application/x-compressed; charset=iso-8859-1 Content-Disposition: attachment; filename="myarchive.tar.gz" Content-Transfer-Encoding: base64 jdaia89uju4vewq+jaoisp90jcdmlagnkjznckjdzn and so on...
4 of 5 12-11-02 02:49 PM Note the new header: Content-Transfer-Encoding. We need to put this for anything that doesn't have a MIME type starting with text/, because that means it's probably binary, and there are several different ways of encoding binary data. Putting it all together, we get: Subject: Archived data Content-Type: application/x-compressed; charset=iso-8859-1 Content-Disposition: attachment; filename="myarchive.tar.gz" Content-Transfer-Encoding: base64 jdaia89uju4vewq+jaoisp90jcdmlagnkjznckjdzn... -- There we go! Now you can send text emails with attachments to all your family and friends. I think this tutorial has gone long enough, so I'll get to HTML emails and embedding stuff in the next tutorial. Posted 01 September 2009-04:27 AM These almost look like tutorials on the mail format. Posted 01 September 2009-04:30 AM Well, you kind of have to know the mail format to send an email... Guest_Jordan_* Posted 01 September 2009-05:18 AM Good tutorial, +rep. Posted 01 September 2009-09:50 AM True. Many of our technologies depend on the protocols. Posted 01 September 2009-02:27 PM Do you think this should be in the General Programming section? I kinda meant it for PHP / Perl / anything else that uses sendmail, but since it was a CLI utility I decided to stick it here.
5 of 5 12-11-02 02:49 PM Posted 02 September 2009-01:10 PM It works as is. Posted 02 September 2009-01:46 PM Ok, good. I'll probably post part three today, I think. Back to Linux Tutorials, Guides and Tips SQL Web Development Forum Database & Database Programming Slow Sql Query Needs Improving, Could Sub Queries Be My Answer. Started by mctim, 30 Jul 2012 SQL, form 2 replies 361 views Software Development C and C++ Regarding A Function Accepting Variable Number Of Arguments In C Started by csepraveenkumar, 01 Jun 2012 form 2 replies 353 views Software Development C and C++ [SOLVED] Working With Data Files In C Started by Agent001, 27 May 2012 form Software Development Java Help Help, I Don't Know Whats Wrong. Started by Chall, 08 May 2012 form HOT 16 replies 569 views 4 replies 380 views Programming Tutorials Classes and Code Snippets Convert Ipv4 Address To Long. Started by farrell2k, 13 Apr 2012 form 1 reply 750 views CODECALL Programming Tutorials Linux Tutorials, Guides and Tips