Software

Pop Quiz Solution: How to use C to initiate an e-mail message with an attachment

TechRepublic member Mike K. submitted the topic for this week's pop quiz, and we awarded Fatbrain.com gift certificates worth $25 to two lucky readers.


TechRepublic member MikeKavenagh, a senior knowledge systems engineer, submitted the topic for this pop quiz. If you’d like to suggest a topic for an upcoming quiz, please send us a note.

The situation
Here’s what Mike wrote: "I have a C program (blackbox) that produces a text file that I would like to send via e-mail as an attachment. The program has enough information to construct an e-mail address and can issue a command line statement via the System function. (This task can easily be accomplished in UNIX using the 'mail' command at the command line.)"

The challenge:
Mike wants to know: "How can I use Outlook or something similar (running on Windows NT) to e-mail a text file from this C program?"
We’re awarding Fatbrain.com gift certificates worth $25 to both Woody McKay and Tom Lundin.
The solutions
Thanks to Tim Gooch, C developer and all-around cool IT guy, for helping us evaluate the solutions to this pop quiz.

According to Tim, if Mr. Kavenagh doesn't want to modify his "C" program or build a new one, the answer that probably answers the question most directly is this one from TechRepublic member Woody McKay, who wrote: “Man! This is such an easy question. Many people use command line e-mailer programs just like the UNIX SENDMAIL program. As a matter of fact, there is a SENDMAIL for NT that can be used from the command line. Another is BLAT, which also e-mails attachments. I use these to e-mail reports built from programs and such. If needed, I can supply the URLs for these and others.”

If Mr. Kavenagh doesn't mind building another program to accept a command-line call and sending the message via MS Outlook, then he should consider this advice from TechRepublic member Tom Lundin: “I can't take credit for formulating this answer, just for digging it up. It comes from the MSDN Library, and it is a snippet of code that shows how to use Visual C++ to send an e-mail message using Outlook. The "Outlook Object Model" that is referenced is simply the OLE (aka COM) services that Outlook exposes as function call interfaces. The file MSOUTL85.OLB, which should be in your Outlook program directory, is the physical manifestation of this object library. I have annotated the code in a few places to add my two bits' worth of experience to the statements.

This code is ostensibly meant to be compiled as a stand-alone command line program (hence, the body main()), but the code within main() can just as well be added to a button on a form if you wanted to do that instead.”
HOWTO: Send a Message by Outlook 98 Object Model with VC++
ID: Q199870
Microsoft Outlook 98
// Change the path to msoutl85.olb if necessary.
   // TOM L. NOTE: If you are using VC++ 6.0 and are adding this code
   // to a button on a form, I think you can add a Reference to MSOUTL85.OLB
   // directly from within the IDE, and comment out the following line...

   #import "C:\\Program Files\\MicrosoftOffice\\Office\\msoutl85.olb"\


   no_namespace exclude("_IRecipientControl", "_DRecipientControl")


   #include <stdio.h>

   #include <tchar.h>

   void dump_com_error(_com_error &e)

   {
    _tprintf(_T("Oops - hit an error!\n"));
    _tprintf(_T("\a\tCode = %08lx\n"), e.Error());
    _tprintf(_T("\a\tCode meaning = %s\n"), e.ErrorMessage());
    _bstr_t bstrSource(e.Source());
    _bstr_t bstrDescription(e.Description());
    _tprintf(_T("\a\tSource = %s\n"), (LPCTSTR) bstrSource);
    _tprintf(_T("\a\tDescription = %s\n"), (LPCTSTR) bstrDescription);
   }

   // If this is placed in the scope of the smart pointers, they must be

   // explicitly Release(d) before CoUninitialize() is called. If any
   // reference count is non-zero, a protection fault will occur.
   struct StartOle {
    StartOle() { CoInitialize(NULL); }
    ~StartOle() { CoUninitialize(); }
   } _inst_StartOle;

   void main()

   {
     try
    {
      NameSpacePtr pNameSpace;
      MAPIFolderPtr pOutbox;
      ItemsPtr pOutboxItems;
      _MailItemPtr pNewMail;
      AttachmentsPtr pAttachments;
      RecipientsPtr pRecipients;
      RecipientPtr pRecipient;

      // Create an Outlook.Application pointer.

      _ApplicationPtr pApp("Outlook.Application");

      // Create NameSpace pointer.

      pNameSpace = pApp->GetNamespace(L"MAPI");

      // Create pointer to the Outbox Folder.

      pOutbox = pNameSpace->GetDefaultFolder(olFolderOutbox);

      // Create pointer to the Messages Collection.

      pOutboxItems = pOutbox->Items;

      // Create pointer to a new message.

      pNewMail = pOutboxItems->Add();

      // Set the Subject of the message.

      pNewMail->Subject = "New Mail Subject";     // TOM L. NOTE: Subject line
can be changed by you

      // Set the Text of the message.

      pNewMail->Body = "New mail body\n";  // TOM L. NOTE: the message text
can be multiline
                                           // if you open a text file and read
and append
                                           // each line to pNewMail->Body

      // Create pointer to the Attachments collection.

      pAttachments = pNewMail->Attachments;

      // Create new Attachment.   TOM L. NOTE: The first argument is the

pathname to the
      //                                       attachment file.  The last
argument is what the
      //                                      title of the attachment will be
in the e-mail
      //                                       message itself.
      pAttachments->Add("c:\\Autoexec.bat", (long)1, (long)(15000),
                       "Autoexec.bat");

      // Create pointer to Recipients Collection.

      pRecipients = pNewMail->Recipients;

      // Add recipient.  TOM L. NOTE: The angle brackets around the address

are required
      //                              (at least they are in the Visual Basic
version)
      //                              or you will receive an error message
complaining about
      //                              there being no addresses to send to.
      //                              This line can be part of a "for" loop if
you want to
      //                              send a message to multiple recipients.
In such a case,
      //                              you might want to change the recipient
type to olBcc, so
      //                              the recipients don't see each other's
addresses.
      pRecipients->Add("<johndoe@mydomain.com>");
      //pRecipients->Type = olBcc;

      // Resolve the recipient address.

      pRecipients ->ResolveAll();

      // Send the message.

      pNewMail->Send();

      _tprintf(_T("Message sent\n"));


      // Logoff NameSpace.

      pNameSpace->Logoff();
    }

     catch (_com_error &e)

     {
       dump_com_error(e);
     }
   }

Share the wealth
To comment on this tip, please post a comment below or drop us a note.

Editor's Picks

Free Newsletters, In your Inbox