a MAPI approach with one attachment

This solution is made by Johann van der Merwe.
It allows one attachment.

{windows.i}
 
RUN mapi ( "you@work.com",
           "yourwife@home.com",
           "late for dinner",
           "something came up..",
           "c:\images\flowers.bmp"
          ).
 
 
/* ========================================================================== */
 
PROCEDURE MAPI :
 
DEFINE INPUT PARAMETER OriginName   AS CHARACTER.
DEFINE INPUT PARAMETER RecipName    AS CHARACTER.
DEFINE INPUT PARAMETER Subject      AS CHARACTER.
DEFINE INPUT PARAMETER Bodytext     AS CHARACTER.
DEFINE INPUT PARAMETER FilePathName AS CHARACTER.
 
 
DEFINE VARIABLE SubjPtr AS MEMPTR.
SET-SIZE(SubjPtr) = LENGTH(Subject) + 1. /* maximum = 255 */ 
PUT-STRING(SubjPtr,1) = Subject.
DEFINE VARIABLE TextPtr AS MEMPTR.
SET-SIZE(TextPtr) = 16000. 
PUT-STRING(TextPtr,1) = Bodytext + (IF FilePathName = "":U 
                                    THEN "":U 
                                    ELSE CHR(10) + CHR(10) + " ":U).   
/* if file attached place at end of Bodytext with line skip */
 
/* ---------------- Build Originator details ------------------------ */
DEFINE VARIABLE OriginNamePtr AS MEMPTR.
SET-SIZE(OriginNamePtr) = LENGTH(OriginName) + 1.  /* maximum = 255 */
PUT-STRING(OriginNamePtr,1) = OriginName.  /* Originator name */
 
DEFINE VARIABLE OriginDescPtr AS MEMPTR.
SET-SIZE(OriginDescPtr) = 24.
PUT-LONG(OriginDescPtr,1) = 0. /* Reserved */ 
PUT-LONG(OriginDescPtr,5) = 0. /* RecipClass 0 = MAPI_ORIG */ 
PUT-LONG(OriginDescPtr,9) = GET-POINTER-VALUE(OriginNamePtr).  /* Name */
PUT-LONG(OriginDescPtr,13) = 0. /* Address */ 
PUT-LONG(OriginDescPtr,17) = 0. /* EID Size */ 
PUT-LONG(OriginDescPtr,21) = 0. /* Entry ID */
 
/* ----------------Build Recipient details -------------------------- */
DEFINE VARIABLE RecipNamePtr AS MEMPTR.
SET-SIZE(RecipNamePtr) = LENGTH(RecipName) + 1./* maximum = 255 */ 
PUT-STRING(RecipNamePtr,1) = RecipName. /* Recipient name */
DEFINE VARIABLE RecipDescPtr AS MEMPTR.
SET-SIZE(RecipDescPtr) = 24.
PUT-LONG(RecipDescPtr,1) = 0. /* Reserved */ 
PUT-LONG(RecipDescPtr,5) = 1. /* RecipClass 1 = MAPI_TO */ 
PUT-LONG(RecipDescPtr,9) = GET-POINTER-VALUE(RecipNamePtr).  /* Name */
PUT-LONG(RecipDescPtr,13) = 0. /* Address */ 
PUT-LONG(RecipDescPtr,17) = 0. /* EID Size */ 
PUT-LONG(RecipDescPtr,21) = 0. /* Entry ID */
 
/* --------------- Build File Details ------------------- */
IF FilePathName <> "":U THEN DO:
   DEFINE VARIABLE FilePathNamePtr AS MEMPTR.
   SET-SIZE(FilePathNamePtr) = LENGTH(FilePathName) + 1.  /* maximum = 255 */
   PUT-STRING(FilePathNamePtr,1) = FilePathName.  /* File pathname */
 
   DEFINE VARIABLE FILENAME AS CHARACTER NO-UNDO.
   FILENAME = SUBSTRING(FilePathName,R-INDEX(FilePathName,"\":U) + 1).
   /* extract filename (starting on last \) from filefullname */
   FILENAME = "     ":U + FILENAME.
   /* for some strange reason the first five chars disappear */
 
   DEFINE VARIABLE FileNamePtr AS MEMPTR.
   SET-SIZE(FileNamePtr) = LENGTH(FILENAME) + 1. /* maximum = 255 */ 
   PUT-STRING(FileNamePtr,1) = FILENAME. /* File name */
 
   DEFINE VARIABLE FileDescPtr AS MEMPTR.
   SET-SIZE(FileDescPtr) = 24.
   PUT-LONG(FileDescPtr,1) = 0. /* Reserved */ 
   PUT-LONG(FileDescPtr,5) = 0. /* Flags 0 = data file */
   PUT-LONG(FileDescPtr,9) = LENGTH(Bodytext) + 2.  /* Position */
   PUT-LONG(FileDescPtr,13) = GET-POINTER-VALUE(FilePathNamePtr).  /* PathName */
   PUT-LONG(FileDescPtr,17) = GET-POINTER-VALUE(FileNamePtr). /* FileName */ 
   PUT-LONG(FileDescPtr,21) = 0. /* FileType */
END.
 
 
 
/* ---------- Build Message Details ------------------- */
DEFINE VARIABLE MessageDescPtr AS MEMPTR.
SET-SIZE(MessageDescPtr) = 48.
PUT-LONG(MessageDescPtr,1) = 0.  /* Reserved */
PUT-LONG(MessageDescPtr,5) = GET-POINTER-VALUE(SubjPtr).  /* Subject */
PUT-LONG(MessageDescPtr,9) = GET-POINTER-VALUE(TextPtr).  /* Text */
PUT-LONG(MessageDescPtr,13) = 0. /* MessageType */ 
PUT-LONG(MessageDescPtr,17) = 0. /* DateReceived */ 
PUT-LONG(MessageDescPtr,21) = 0. /* ConversationID */ 
PUT-LONG(MessageDescPtr,25) = 1.  /* Flags */
PUT-LONG(MessageDescPtr,29) = GET-POINTER-VALUE(OriginDescPtr).  /* Originator */
PUT-LONG(MessageDescPtr,33) = 1.  /* RecipCount */
PUT-LONG(MessageDescPtr,37) = GET-POINTER-VALUE(RecipDescPtr).  /* Recips */
PUT-LONG(MessageDescPtr,41) = (IF FilePathName = "":U 
                                  THEN 0 
                                  ELSE 1).  /* FileCount */
PUT-LONG(MessageDescPtr,45) = (IF FilePathName = "":U 
                                  THEN 0 
                                  ELSE GET-POINTER-VALUE(FileDescPtr)).                             /* Files */
/* EO Build Message Details */
 
 
/* -------- Send Message ------------ */
DEFINE VARIABLE ResultInt AS INTEGER NO-UNDO.
RUN MAPISendMail IN hpApi
 (INPUT 0,
  INPUT 0,
  INPUT GET-POINTER-VALUE(MessageDescPtr),
  INPUT 11, /* 1 = MAPI_LOGON_UI + 2 = MAPI_NEW_SESSION + 8 = MAPI_DIALOG */
  INPUT 0,     
  OUTPUT ResultInt). 
 
RUN MapiReturnCode (ResultInt).
 
/* ------- Free memory ------------ */
SET-SIZE(SubjPtr)         = 0.
SET-SIZE(TextPtr)         = 0. 
SET-SIZE(OriginNamePtr)   = 0.
SET-SIZE(OriginDescPtr)   = 0.
SET-SIZE(RecipNamePtr)    = 0.
SET-SIZE(RecipDescPtr)    = 0.
SET-SIZE(FilePathNamePtr) = 0.
SET-SIZE(FileNamePtr)     = 0.
 
END PROCEDURE.

= A Simple MAPI Approach, Multiple Attachments and Recipients

=
This solution is by Ian Richards. A COM solution is easier, but this allows me to send automated e-mails from a server where Outlook is not installed. The recipients and attachments are presented as comma separated lists.

{windows.i}
 
RUN mapimulti( 
  INPUT "you@originator.com",
  INPUT "recipient1@address1.com,recipient2@address2.com",
  INPUT "Message Title",
  INPUT "Message Text",
  INPUT "C:\file1.txt,C:\file2.txt").
/* ========================================================================== */
PROCEDURE mapimulti:
{windows.i}
DEFINE INPUT PARAMETER ipOrigName     AS CHARACTER NO-UNDO.                 /* Originator Name */
DEFINE INPUT PARAMETER ipRecipName    AS CHARACTER NO-UNDO.                 /* Recipient(s) names, comma separated */
DEFINE INPUT PARAMETER ipSubject      AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER ipBodytext     AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER ipFilePathName AS CHARACTER NO-UNDO.                 /* Attachment(s) names, comma separated */ 
DEFINE VARIABLE intRecips AS INTEGER NO-UNDO.                               /* Count Recipients */
DEFINE VARIABLE intAttachs AS INTEGER NO-UNDO.                              /* Count Attachments */
DEFINE VARIABLE RecipName AS CHARACTER EXTENT 20 NO-UNDO.                   /* Recipient Array */
DEFINE VARIABLE FilePathName AS CHARACTER EXTENT 20 NO-UNDO.                /* Attachment Array */ 
/* Memptr Definitions */
DEFINE VARIABLE SubjPtr AS MEMPTR NO-UNDO.                                  /* Message Subject */
DEFINE VARIABLE TextPtr AS MEMPTR NO-UNDO.                                  /* Message Text */
DEFINE VARIABLE OriginNamePtr AS MEMPTR.                                    /* Originator Name */
DEFINE VARIABLE RecipNamePtr AS MEMPTR EXTENT 20 NO-UNDO.                   /* Array of pointers to Recipient Name */
DEFINE VARIABLE RecipDescPtr AS MEMPTR EXTENT 20 NO-UNDO.                   /* Array of pointers to Recipient Description */
DEFINE VARIABLE FilePathNamePtr AS MEMPTR EXTENT 20 NO-UNDO.                /* Array of pointers to Attachment Path */
DEFINE VARIABLE FileNam AS CHARACTER EXTENT 20 NO-UNDO.                     /* Array of Attachment Name */
DEFINE VARIABLE FileNamPtr AS MEMPTR EXTENT 20 NO-UNDO.                     /* Array of pointers to Attachment Name */
DEFINE VARIABLE FileDescPtr AS MEMPTR EXTENT 20 NO-UNDO.                    /* Array of pointers to Attachment Description */ 
DEFINE VARIABLE MessageDescPtr AS MEMPTR NO-UNDO.                           /* Pointer To Message Structure */
DEFINE VARIABLE FileArrayPtr AS MEMPTR NO-UNDO.                             /* Pointer to Array of File Decription */
DEFINE VARIABLE RecipArrayPtr AS MEMPTR NO-UNDO.                            /* Pointer to Array of Recipient */
DEFINE VARIABLE zz AS INTEGER NO-UNDO.                                      /* General Purpose Integer */
/* --- POPULATE RECIPIENT & ATTACHMENT ARRAYS -------*/
RUN recips.     /* Populate RecipName */
RUN attachs.    /* Populate FilePath Name */
                                                                                
/* --- SET MESSAGE TEXT AND SUBJECT -----------------*/
SET-SIZE(SubjPtr) = LENGTH(ipSubject) + 1.                                  /* maximum = 255 */ 
PUT-STRING(SubjPtr,1) = ipSubject.
SET-SIZE(TextPtr) = 16000. 
PUT-STRING(TextPtr,1) = ipBodytext. 
/* --- BUILD ORIGINATOR DETAILS ---------------------*/
SET-SIZE(OriginNamePtr) = LENGTH(ipOrigName) + 1.                           /* maximum = 255 */
PUT-STRING(OriginNamePtr,1) = ipOrigName.                                   /* Originator name */
 
DEFINE VARIABLE OriginDescPtr AS MEMPTR.
SET-SIZE(OriginDescPtr) = 24.
PUT-LONG(OriginDescPtr,1) = 0.                                              /* Reserved */ 
PUT-LONG(OriginDescPtr,5) = 0.                                              /* RecipClass 0 = MAPI_ORIG */ 
PUT-LONG(OriginDescPtr,9) = GET-POINTER-VALUE(OriginNamePtr).               /* Name */
PUT-LONG(OriginDescPtr,13) = 0.                                             /* Address */ 
PUT-LONG(OriginDescPtr,17) = 0.                                             /* EID Size */ 
PUT-LONG(OriginDescPtr,21) = 0.                                             /* Entry ID */
/* ---------- BUILD RECIPIENT DETAILS -------------- */
DO zz = 1 TO intRecips :
    SET-SIZE(RecipNamePtr[zz]) = LENGTH(RecipName[zz]) + 1.                 /* maximum = 255 */ 
    PUT-STRING(RecipNamePtr[zz],1) = RecipName[zz].                         /* Recipient name */
    SET-SIZE(RecipDescPtr[zz]) = 24.
    PUT-LONG(RecipDescPtr[zz],1) = 0.                                       /* Reserved */ 
    PUT-LONG(RecipDescPtr[zz],5) = 1.                                       /* RecipClass 1 = MAPI_TO */ 
    PUT-LONG(RecipDescPtr[zz],9) = GET-POINTER-VALUE(RecipNamePtr[zz]).     /* Name */
    PUT-LONG(RecipDescPtr[zz],13) = 0.                                      /* Address */ 
    PUT-LONG(RecipDescPtr[zz],17) = 0.                                      /* EID Size */ 
    PUT-LONG(RecipDescPtr[zz],21) = 0.                                      /* Entry ID */
END.
/* Populate Memory Indicated By RecipArrayPtr */
SET-SIZE(RecipArrayPtr) = 24 * intRecips.
DO zz = 1 TO intRecips :
    PUT-BYTES(RecipArrayPtr, (zz * 24) - 23)  = GET-BYTES(RecipDescPtr[zz],1,24).
END.
/* ---------- BUILD FILE DETAILS ------------------- */
/* Build File Description Array */
DO zz = 1 TO intAttachs:
    
    SET-SIZE(FilePathNamePtr[zz]) = LENGTH(FilePathName[zz]) + 1.           /* maximum = 255 */
    PUT-STRING(FilePathNamePtr[zz],1) = FilePathName[zz].                   /* File pathname */
 
    FileNam[zz] = SUBSTRING(FilePathName[zz],R-INDEX(FilePathName[zz],"\":U) + 1).
 
    SET-SIZE(FileNamPtr[zz]) = LENGTH(FileNam[zz]) + 1.                     /* maximum = 255 */ 
    PUT-STRING(FileNamPtr[zz],1) = FileNam[zz].                             /* File name */
 
    SET-SIZE(FileDescPtr[zz]) = 24.
    PUT-LONG(FileDescPtr[zz],1) = 0.                                        /* Reserved */ 
    PUT-LONG(FileDescPtr[zz],5) = 0.                                        /* Flags 0 = data file */
    PUT-LONG(FileDescPtr[zz],9) = -1.                                       /* Position */
    PUT-LONG(FileDescPtr[zz],13) = GET-POINTER-VALUE(FilePathNamePtr[zz]).  /* PathName */
    PUT-LONG(FileDescPtr[zz],17) = GET-POINTER-VALUE(FileNamPtr[zz]).       /* File Name */ 
    PUT-LONG(FileDescPtr[zz],21) = 0.                                       /* FileType */
END.
/* Populate Memory Indicated By FileArrayPtr */
SET-SIZE(FileArrayPtr) = 24 * intAttachs.
DO zz = 1 TO intAttachs:
    
    PUT-BYTES(FileArrayPtr, (zz * 24) - 23)  = GET-BYTES(FileDescPtr[zz],1,24).
    
END.
/* ---------- BUILD MESSAGE DETAILS ---------------- */
SET-SIZE(MessageDescPtr) = 48.
PUT-LONG(MessageDescPtr,1) = 0.                                             /* Reserved */
PUT-LONG(MessageDescPtr,5) = GET-POINTER-VALUE(SubjPtr).                    /* Subject */
PUT-LONG(MessageDescPtr,9) = GET-POINTER-VALUE(TextPtr).                    /* Text */
PUT-LONG(MessageDescPtr,13) = 0.                                            /* MessageType */ 
PUT-LONG(MessageDescPtr,17) = 0.                                            /* DateReceived */ 
PUT-LONG(MessageDescPtr,21) = 0.                                            /* ConversationID */ 
PUT-LONG(MessageDescPtr,25) = 1.                                            /* Flags */
PUT-LONG(MessageDescPtr,29) = GET-POINTER-VALUE(OriginDescPtr).             /* Originator */
PUT-LONG(MessageDescPtr,33) = intRecips.                                    /* RecipCount */
PUT-LONG(MessageDescPtr,37) = GET-POINTER-VALUE(RecipArrayPtr).             /* Recips */
PUT-LONG(MessageDescPtr,41) = intAttachs.                                   /* FileCount */
PUT-LONG(MessageDescPtr,45) = GET-POINTER-VALUE(FileArrayPtr).              /* Files */
/* ---------- SEND MESSAGE ------------------------- */
DEFINE VARIABLE ResultInt AS INTEGER NO-UNDO.
RUN MAPISendMail IN hpApi
 (INPUT 0,
  INPUT 0,
  INPUT GET-POINTER-VALUE(MessageDescPtr),
  INPUT 0,                                                                  /* 1 = MAPI_LOGON_UI + 2 = MAPI_NEW_SESSION + 8 = MAPI_DIALOG */
  INPUT 0,     
  OUTPUT ResultInt). 
 
IF ResultInt <> 0 THEN RUN MapiReturnCode.p (INPUT ResultInt).
 
/* ---------- RELEASE RESOURCES -------------------- */
SET-SIZE(SubjPtr) = 0.
SET-SIZE(TextPtr) = 0. 
DO zz = 1 TO intAttachs :
    SET-SIZE(FilePathNamePtr[zz]) = 0.
    SET-SIZE(FileNamPtr[zz])     = 0.
    SET-SIZE(FilePathNamePtr[zz]) = 0.
    SET-SIZE(FileDescPtr[zz])     = 0.
END.
DO zz = 1 TO intRecips :
    SET-SIZE(RecipNamePtr[zz])    = 0.
    SET-SIZE(RecipDescPtr[zz])    = 0.
END.
SET-SIZE(MessageDescPtr) = 0.
SET-SIZE(FileArrayPtr) = 0.
SET-SIZE(RecipArrayPtr) = 0.
SET-SIZE(OriginNamePtr) = 0.
IF VALID-HANDLE(hpAPI) THEN DELETE OBJECT hpAPI.
/* ---------- INTERNAL PROCEDURES ------------------ */
PROCEDURE recips:
/* --------------------------------------------*/
/*    Populate Reciptient Array, RecipName,    */
/*    from comma separated list.               */         
/*---------------------------------------------*/    
    DEFINE VARIABLE xx AS INTEGER NO-UNDO.
    IntRecips = 0.
    DO WHILE ipRecipName <> "":
        xx = INDEX(ipRecipName, ",").
        IF xx > 0 THEN DO:
            intRecips = intRecips + 1.
            RecipName[intRecips] = SUBSTRING(ipRecipName, 1, xx - 1).
            ipRecipName = SUBSTRING(ipRecipName, xx + 1).
        END.
        ELSE DO:
            IF ipRecipName <> "" THEN DO:
                intRecips = intRecips + 1.
                RecipName[intRecips] = ipRecipName.
                ipRecipName = "".
            END.
        END.
    END.
END PROCEDURE.
PROCEDURE attachs:
/* --------------------------------------------*/
/*    Populate Attachment Array, FilePathName  */
/*    from comma separated list.               */         
/*---------------------------------------------*/ 
    DEFINE VARIABLE yy AS INTEGER NO-UNDO.
    IntAttachs = 0.
    DO WHILE ipFilePathName <> "":
        yy = INDEX(ipFilePathName, ",").
        IF yy > 0 THEN DO:
            intAttachs = intAttachs + 1.
            FilePathName[intAttachs] = TRIM(SUBSTRING(ipFilePathName, 1, yy - 1)).
            ipFilePathName = TRIM(SUBSTRING(ipFilePathName, yy + 1)).
        END.
        ELSE DO:
            IF ipFilePathName <> "" THEN DO:
                intAttachs = intAttachs + 1.
                FilePathName[intAttachs] = TRIM(ipFilePathName).
                ipFilePathName = "".
            END.
        END.
    END.
END PROCEDURE.
END PROCEDURE.

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Question

It seems that Outlook (& Express) always uses the default account to send mails using the here-above codes (even if you specify another 'originator').
Do you have any tip to force Outlook to use the 'originator' account (if defined, of course)?
Thanks in advance