January Eighth 2003 From: Bob Zale, President PowerBASIC, Inc. PowerBASIC Gazette CyberEdition #33 =================================== Subject: Sending E-mail with attachments ========================================= There's lots of excitement at PowerBASIC this month. Our web site at http://www.powerbasic.com will see major changes. Our new compilers have been a huge success. PowerBASIC FORMS, our new visual designer, has changed the way folks write GUI code. If you still haven't upgraded, it's time to get moving! But more about that later... Right now, we have important things to talk about. You know, our latest Win32 compilers, PB/CC 3 and PB/Win 7, offer full support for TCP and UDP communications. They'll let you send e-mail, from any program, in just a few lines of code. You can check incoming e-mail, even access an FTP site, or download a web page. Great stuff... But how does it really work? And how can you take advantage in your own programs? Give me a minute and you'll get all the inside information, right here in the PowerBASIC Gazette. We've prepared a series of articles on just these topics. The first two installments, an overview of TCP and "Sending E-mail with PowerBASIC", were published in previous Gazettes, and can be found on our web site at http://www.powerbasic.com. The third in the series, "Sending E-mail File Attachments With PowerBASIC", follows below. Stay tuned right here, and you'll be a TCP/IP expert in no time at all! If you still haven't upgraded to PB/CC 3, or PB/Win 7, today is the day to do so. Check out all of the product details especially our new visual designer "PowerBASIC FORMS", at http://www.powerbasic.com and join in the fun! {smile} Pricing and ordering information can be found at the very end of this Gazette. Questions? Just e-mail us at info@powerbasic.com We'll do our very best to help. Regards, Bob Zale, President PowerBASIC, Inc. =================================================================== =================================================================== Sending E-mail File Attachments With PowerBASIC =============================================== By Tony Jones and Lance C. Edmonds, PowerBASIC, Inc. When it comes to writing E-mail programs, most programmers will say "been there, done that". But when it comes to writing an E-mail program that can send file attachments, a lot of programmers are left scratching their heads. Well, wonder no more... we are about to reveal the mysteries behind sending file attachments! Introducing MIME ================ MIME (Multipurpose Internet Mail Extensions) provides a method of sending non-ASCII content, such as binary files, through the Internet E-mail system. E-mail was designed to send and receive text. "Attachments" which are not in text format must be converted to text format (encoded) to be sent through E-mail. MIME attachments are restored to their original formats (decoded) when received. Encoding Methods ================ MIME provides two types of encoding methods: "Quoted-Printable" and "Base64". Quoted-Printable was designed for data that consists largely of ASCII (text) characters, but that also contain some non-ASCII characters. The general idea behing this method of encoding is to leave the ASCII characters alone and just encode the non-ASCII characters. Base64 was designed to encode arbitrary, binary data (.JPG and .WAV files are just two examples), and this is what we will focus on for this article. Base64 Encoding: How it works ============================= The Base64 algorithm works by first taking three 8-bit input groups of data to form a 24-bit input string and then taking this 24-bit input string and breaking it down into four 6-bit input groups. Each of these four 6-bit input groups is then indexed into the Base64 alphabet which is comprised of 64 ASCII characters. The result of each index is then output as the encoded character. This sample code performs just that: ' Loop through our entire Input Buffer FOR Counter& = 1 TO LEN(InBuffer$) STEP 3 ' First get three 8-bit input groups of data Group1& = ASC(MID$(InBuffer$, Counter&, 1)) Group2& = ASC(MID$(InBuffer$, Counter& + 1, 1) + $NUL) Group3& = ASC(MID$(InBuffer$, Counter& + 2, 1) + $NUL) ' We have our 24-bit input string, ' so break it down into four 6-bit input groups Input1% = Group1& \ 4 Input2% = (Group1& AND 3) * 16 + (Group2& \ 16) Input3% = (Group2& AND 15) * 4 + (Group3& \ 64) Input4% = Group3& AND 63 NEXT Counter& At this point our input data looks like this: Input1% contains the high order bits of Group1 Input2% contains the low order bits of Group1 and the high order bits of Group2 Input3% contains the low order bits of Group2 and the high order bits of Group3 Input4% contains the low order bits of Group3 Now all thats left to do is encode the data by indexing into the Base64 alphabet like this. ' The Base64 alphabet $Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" & _ "abcdefghijklmnopqrstuvwxyz0123456789+/" ... Mime$ = Mime$ & MID$($Base64, Input1% + 1, 1) Mime$ = Mime$ & MID$($Base64, Input2% + 1, 1) Mime$ = Mime$ & MID$($Base64, Input3% + 1, 1) Mime$ = Mime$ & MID$($Base64, Input4% + 1, 1) It's a fairly straight forward algorithm to implement, but there is one special case the code must handle -- unless the length of the data being encoded is an exact multiple of 3, then we must pad the last remaining bytes with zeros to create a complete 24-bit block for the encoding algorithm. Performance =========== While the algorithm presented above is perfectly functional, there is certainly room for some optimzation and performance tweaking (in true PowerBASIC style!). For example, by making use of a pre-allocated string buffer to hold the encoded data, and the careful use of some Byte Pointer variables, we can make that MIME encoding routine really sizzle! Detailing these optimizations is outside of the scope of this article, but you can check them out by downloading the example program code that we've written to accompany this article. You'll find it at: http://www.powerbasic.com/files/pub/pbwin/inet/mailfile.zip Sending a file attachment ========================= Now that we know how to encode a file using Base64, we're ready to create a MIME attachment and send it on its way. The first thing we need to do is construct a mail header, much like you would for sending an ordinary, plain text message, but with the addition of a few MIME-specific fields. Have a look at the following sample: ' The main E-mail header TCP PRINT hTCP, "From: " & $MailFrom TCP PRINT hTCP, "To: " & $MailTo TCP PRINT hTCP, "Subject: " & $Subject TCP PRINT hTCP, "X-Mailer: MIME/Base64 E-mail Demo Version 1.0" Up to this point it looks the same as a regular mail header, but now we need to add a few new fields to the header: TCP PRINT hTCP, "MIME-Version: 1.0" The first new field is "MIME-Version". This field is required by all MIME messages. It describes the version of MIME used to compose the message and ensures that the message complies with MIME formatting conventions. $Bound = """Boundary.marker.12345""" ' User-defined boundary marker ... TCP PRINT hTCP, "Content-Type: multipart/mixed; boundary=" & $Bound Now we've added a field "Content-Type". This field is used to describe the type of data within a message and it consists of a "type/subtype". There are seven standard pre-defined types, but for our purposes, we'll only take a look at few: The first combination is "multipart/mixed". This Content-Type is used when a message consists of one or more sub-body types, such as plain ASCII text and perhaps a file attachment. Each body type is seperated from the other by something called an "encapsulation boundary". This is nothing more complex than a user-defined string, specified with the boundary parameter as shown in the above code. In our simple example, we've used a string equate to hold the boundary string, but a real application should produce a unique boundary for each message being sent, for example, by incorporating a random number or message counter value, etc. TCP PRINT hTCP, "" TCP PRINT hTCP, "--" & $Bound As shown above, boundaries begin with two leading hyphens, followed by the boundary string. TCP PRINT hTCP, "Content-Type: text/plain; charset=" & """us-ascii""" TCP PRINT hTCP, "Content-Transfer-Encoding: 7bit" TCP PRINT hTCP, "" The next Content-Type is "text/plain". This type/subtype is used to designate that the body type is plain ASCII text using the character set designated by the "charset" parameter. The "Content-Transfer-Encoding" field describes the type of encoding that has been applied to the following section of the E-mail body. In the above example, "7bit" indicates that this part of the message contains normal, ASCII characters. After sending those headers, we send the main message body: TCP PRINT hTCP, "Test message line 1." TCP PRINT hTCP, "Test message line 2." ... Now we need to create another body type so that we can send our file attachment: TCP PRINT hTCP, "--" & $Bound TCP PRINT hTCP, "Content-Type: application/octet-stream; name=" & $DQ & File & $DQ TCP PRINT hTCP, "Content-Transfer-Encoding: base64" TCP PRINT hTCP, "" The Content-Type "application/octet-stream" (as shown above) is typically used for designating raw binary data, such as a file. The parameter name in the above is used to designate the name of the file. Now all that's left to do is encode our data using the Base64 algorithm as described earlier and send it on its way, as in the following snippet: ' Assumes the entire file has been read into Attachment$ MimeData$ = MimeEncode$(Attachment$) FOR Counter& = 1 TO LEN(MimeData$) STEP 76 IF LEN(MimeData$) - Counter& >= 76 THEN TCP PRINT hTCP, MID$(MimeData$, Counter&, 76) ELSE TCP PRINT hTcp, Mid$(MimeData$, Counter&) & "=" END IF NEXT Counter& At this point, you may be wondering about the IF statement in the above code? With MIME, line lengths are limited to a maximum of 76 characters, so we loop through the encoded string, sending 76 character chunks. In most instances, the MIME-encoded data will not have a length that is an exact multiple of 76, so it is quite likely we will be left with a residual chunk of less than 76 bytes to deal with. In this situation, we simply append an equality character ("=") to signal that the last line has been padded. Finally, we signal the end of the boundary with the addition of two trailing hyphens to the boundary string: TCP PRINT hTCP, "--" & $Bound & "--" Then, we can follow the normal methods of signalling the SMTP server that the E-mail is complete. And there we have it, an email with a complete file attachment has been sent. Pretty cool stuff, don't you think? Précis ====== I hope we've been able to shed some light on sending file attachments using MIME and Base64 encoding. If you require more information on MIME, then you can review the complete MIME specification in RFC's 1521 and 1522 -- these can be found at: http://www.powerbasic.com/files/pub/docs/RFC/ Finally, a complete example program demonstrating the techniques described in this article (including our optimized MIME encoding routine!) can be downloaded from our web site MAILFILE.ZIP at: http://www.powerbasic.com/files/pub/pbwin/inet =================================================================== =================================================================== Compilers... Compilers... Compilers... Just in case you haven't yet upgraded both compilers, give it some thought now. We're extending Intro Pricing. So, you can still upgrade PB/DLL 6 to PowerBASIC 7 for Windows at just $99, upgrade PB/CC 2 to PB/CC 3 at just $89! Then Drag'n'Drop dialog designs with PowerBASIC Forms for only $99! PB/CC is our Console Compiler -- with a text mode interface to 32-bit Windows. PB 7 for Windows is oriented towards a GUI (graphical user interface) for a typical Windows "look and feel". With all of the new extensions, you won't believe how easy it is to build real GUI applications! PB/Forms is our new, state-of-the-art visual designer. It works with PowerBASIC 7 to build GUIs almost as fast as you can imagine them! You'll drag'n'drop controls, quickly build complex menus, create resources automatically from your images and version info. Create and name your own favorite styles. Import GUI designs from Visual Basic, a resource editor like Visual Studio, even automate hand written DDT code. You'll like this one a lot... It's virtually everything you could ask for in a new RAD tool. For more info, click http://www.powerbasic.com/products/pbforms/ Oh, and our new compilers offer macros, which are not often found in a high level language. Essentially, a Macro invokes a text substitution engine which allows you to extend the PowerBASIC language in ways not seen before. We have single line macros, multi-line macros, even function macros which return a result. And best of all, they don't occupy one byte of code space unless actually used. With PowerBASIC macros, you can design your own personal language! Then there's Client COM services, and the Automation Interface. Now you can tap the power of components. Invoke libraries and full applications with ease, all controlled from your PowerBASIC client program. Invoke Microsoft Word, load and edit documents, all under control of your PowerBASIC program. Do you need ADO or DAO? It's waiting for you! The PowerBASIC IDE had a serious makeover. Selectable color syntax highlighting with options. Printed listings in color. Mouse wheel scrolling. Untold levels of undo. Better debugging, with intuitive watch/unwatch variable selections. The new Code Finder window shows Sub and Function names, aliases, type, and line number. Sort on any column, in either direction, even change the column order. This and more make the new IDE a joy to use. Debugging? We have a whole array of new tools! PROFILE creates a report of program execution. A list of every Sub and Function, the number of times called, and the total elapsed time spent executing all instances of each procedure. CALLSTK allows you to capture a representation of all the stack frames. It answers "How did I get here?". TRACE generates a log which contains an explicit report of each Sub, Function, Label, and Trace Print statement executed, along with parameter and return values, and each error code generated. It answers "Where have I been?", and "How did I get here?" Did I mention that Functions can now take 32 parameters? Or all the new language functions? How about #BLOAT, #STACK, #TOOLS, ACCEL, ACODE$(), ARRAYATTR, BIT CALC, CALLSTK$(), CHOOSE, CLSID$, CSET, ERROR$(), FILESCAN, FUNCNAME$, GUID$(), GUIDTXT$(), IIF(), INTERFACE, JOIN$(), MOUSEPTR, OBJECT, OBJPTR(), OBJRESULT, PARSE, PROGID$, RETAIN$(), SWITCH, TAB$(), UCODE$(), VARIANT(), and lots more. We've even added USING$() with unlimited parameters for fixed-field format, and TRY..CATCH..FINALLY..END TRY adds structure for run-time error handling. Of course, DDT has been expanded with a raft of new functionality! Add a splash of color, change fonts, utilize the new user data area, force a redraw, post or send a message, assign icons and text with ease... all in easy-to use DDT functions. More information? Sure, it's very simple. Just click to go to each or all of the PowerBASIC product pages... PB/CC 3.0: http://www.powerbasic.com/products/pbcc/ PB/WINDOWS 7.0: http://www.powerbasic.com/products/pbdll32/ PowerBASIC Forms: http://www.powerbasic.com/products/pbforms/ Graphics Tools: http://www.powerbasic.com/products/graftool/ PB/WIN 7.0 is attractively priced at $199.00, while PB/CC 3.0 is just $169.00. Upgrades from the prior versions are just $99 and $89. PowerBASIC Forms is priced at $99. Graphics Tools Standard and Pro are $69.95 and $139.95. You can order with ease by just replying to this email. You can call us at (888) 659-8000 or (941) 473-7300, fax us at (941) 681-3100, place an electronic order on our web site (www.powerbasic.com), or even mail it in. But no matter the method you choose, please do it today and do it with confidence. Every product PowerBASIC ships for physical delivery is offered with a money-back guarantee for a full 30 days from the transaction date. Regards, Bob Zale, President PowerBASIC Inc. =================================================================== PowerBASIC Price List ------------------------------------------------------------------- PB/CC Console Compiler 3.0 - Full Product $169.00 PB/CC Console Compiler 3.0 - Upgrade from vs 2 89.00 PB/CC Console Compiler 3.0 - Upgrade from vs 1 119.00 Add Printed Documentation 39.00 ------------------------------------------------------------------- PowerBASIC for Windows 7.0 (GUI) - Full Product $199.00 PowerBASIC for Windows 7.0 - Upgrade from ver 6 99.00 PowerBASIC for Windows 7.0 - Upgrade from prior versions 129.00 Add Printed Documentation 39.00 PowerBASIC Forms Visual Design Tool for PB/Win 7 99.00 ------------------------------------------------------------------- PowerBASIC for DOS 3.5 - Full Product $99.00 PowerBASIC for DOS 3.5 - Upgrade from prior versions 49.00 Add Printed Documentation (2 book set) 29.00 ------------------------------------------------------------------- PowerTree BTree Manager for DOS and Windows $99.00 PB/Vision for DOS 20.00 PB/Xtra III for DOS and Windows 49.00 ------------------------------------------------------------------- Graphics Tools Standard ver 2 $69.95 Graphics Tools Professional ver 2 139.95 Console Tools Standard 49.95 Console Tools Professional 99.95 SQL Tools Standard Version 99.95 SQL Tools Professional Version 199.95 ------------------------------------------------------------------- Shipping/Handling costs: Software & Each Any Software 1 book Addl Book Email $6 N/A N/A UPS Ground/Mail US $10 $10 $6 Fedex 2-day US $16 $16 $6 Fedex 1-day US $28 $28 $6 Air Mail Canada/Mex $12 $22 $6 Fedex Canada/Mexico $22 $32 $6 Air Mail Other Intl $16 $28 $6 Fedex Other Intl $34 $44 $6 PB/Dos Book Set is calculated at a single book rate. ------------------------------------------------------------------- Order online at https://www.powerbasic.com/shop/ (secure server) or just send an email with all pertinent information to sales@powerbasic.com and we'll take it from there! ------------------------------------------------------------------- Most PowerBASIC products (those without printed books) can now be delivered by electronic mail. No wait for a package to arrive... No high shipping costs... For just $6 per order, no matter how many products, we'll deliver directly to your computer. If you're outside the U.S., savings might be greater. You won't pay taxes or duties to a freight company or postal service because they aren't involved in the delivery. Check your tax code to be sure, but some countries charge no tax at all on transactions like this. It could just be your lucky day! ==================================================================== Is your PowerBASIC Gazette Electronic Edition subscription coming to you at home or work? If you don't want to miss a single issue, why not subscribe from both email addresses? Send your subscription request to email@powerbasic.com and please include your name and all email addresses you'd like to add as well as your Zip or Postal Code. If you know someone else who would enjoy this newsletter please forward a copy to them so they can subscribe. ==================================================================== All contents Copyright (c) 2003-2009 PowerBASIC Inc All Rights Reserved. PowerBASIC is a registered trademark of PowerBASIC, Inc. PB/CC, PB/DLL, PB/Win, PowerTREE, and PowerBASIC Forms are trademarks of PowerBASIC Inc. Other names are trademarks or registered trademarks of their respective owners. ==================================================================== PowerBASIC Gazette - Electronic Edition Volume 1 - Issue 33 PowerBASIC, Inc. (888) 659-8000 Sales 2061 Englewood Road (941) 473-7300 Voice Englewood, FL 34223 (941) 681-3100 Fax Visit http://www.powerbasic.com email to sales@powerbasic.com This newsletter is only sent to email addresses in our subscription list. If you have received this newsletter by mistake or no longer wish to receive it, please send a simple unsubscribe request to gazette@powerbasic.com with your name and zip/postal code. ====================================================================