libsmtp API User Manual

Version 1.0.01

 

Version

Date

Change Log

V1.0.00

2008/12/05

1.      Document created

V1.0.01

2009/01/08

1.      Specify the environment tested

V1.0.02

2011/02/23

1.      Add libsmtp_multipart_end API

2.      Update example code

 

Description

Libsmtp allows programs to send mail directly through SMTP (no sendmail needed) and attaching and encoding mail in MIME standards. It is licensed under the LGPL. It is designed to be simple, secure, and small. It can send mail to multiple recipients in one go, and supports sending to CC and BCC recipients too. The development version has support for attachments (this being multiple body parts), different character sets and transport encodings.

This document introduces the wrapped APIs which support a friendly interface to send email can easier. This document provides an example and a figure of Calls Flow for user to understand how to use these APIs.

 

Requirements

        Glib 1.2.0 (Build perquisite)

        Please install above glib 1.2.0 library before using libsmtp library.

 

 

libsmtp_session_initialize

        Initialize the session structure.

<SYNOPSIS>

#include <libsmtp.h>

struct libsmtp_session_struct *libsmtp_session_initialize(void);

<DESCRIPTION>

What you should setup before you initiate a connection .Use this function to initialize the session structure. This will malloc memory and initialize the structure's GStrings and GLists. Please be sure to clean the initialized struct up with libsmtp_free after you finish using it. Session data is saved in a struct pointer that is passed between all functions, so that you can have multiple sessions running at any one time.This is the definition of the struct:

 

struct libsmtp_session_struct {

  int serverflags;                            /* Server capability flags */

  int socket;                                    /* socket handle */

  /* authorization */

  int server_auth, auth_type;

  GString *username;

  GString *password;

  unsigned short pop3port;

  GString *pop3server;

 

  GString *From;                            /* From address */

  GList *To;                                    /* All recipients addresses */

  GList *CC;                                    /* All Carbon Copy recipients addresses */

  GList *BCC;                                 /* All Blind Carbon Copy recipients addresses */

  int NumFailedTo;                         /* number of rejected recipients */

  int NumFailedCC;                        /* number of rejected CC recipients */

  int NumFailedBCC;                      /* number of rejected BCC recipients */

  GList *ToResponse;                     /* List of failed recipients containing the response for each failure */

  GList *CCResponse;                    /* The same for CC recipients */

  GList *BCCResponse;                  /* And for BCC recipients */

 

  GString *Subject;                                /* Mail subject */

  GString *LastResponse;              /* Last SMTP response string from server */

  int LastResponseCode;                /* Last SMTP response code from server */

  int ErrorCode;                             /* Internal libsmtp error code from last error */

  GString *ErrorModule;               /* Module were error was caused */

  int Stage;                                     /* SMTP transfer stage */

 

  unsigned int DialogueSent;         /* Number of SMTP dialogue lines sent */

  unsigned int DialogueBytes;       /* Bytes of SMTP dialogue data sent */

  unsigned int HeadersSent;          /* Number of header lines sent */

  unsigned int HeaderBytes;          /* Bytes of header data sent */

  unsigned long int BodyBytes;      /* Bytes of body data sent */

 

  #ifdef WITH_MIME

    GNode *Parts;                         /* N-Tree of body parts (MIME stuff) */

    int NumParts;                          /* Number of body parts */

    struct libsmtp_part_struct *PartNow;    /* Part we are sending now */

    GNode *PartNowNode;           /* Node of the part we are just sending */

        struct libsmtp_part_struct * mainpart; /* main part header */

  #endif

};

 

 

<PARAMETERS>

        None

<RETURN VALUE>

        libsmtp_session_initialize() returns the session structure pointer to the newly allocated memory, or NULL if the request fails.

 

 

libsmtp_set_environment

<SYNOPSIS>

#include < libsmtp.h>

int libsmtp_set_environment (char *libsmtp_int_From, char *libsmtp_int_Subject,

                       unsigned int libsmtp_int_flags, struct libsmtp_session_struct *libsmtp_session)

<DESCRIPTION>

        With this function you can set additional session parameters for this session. This should be set before the dialogue is begun.

<PARAMETERS>

libsmtp_int_From

Address of the sender
libsmtp_int_Subject

Subject line of message

libsmtp_int_flags

libsmtp_int_flags doesn't have any meaning at the moment.

libsmtp_session

A handle returned by libsmtp_session_initialize ().

<RETURN VALUE>

Returns: 0 for success (see libsmtp_errno)

 

 

libsmtp_set_authorization

        Enable authentication and optionally choose the method.

<SYNOPSIS>

#include < libsmtp.h>

int libsmtp_set_authorization(unsigned int Auth_type, char *auth_username, char *auth_password, unsigned short pop_port, char *pop_server, struct libsmtp_session_struct *libsmtp_session)

<DESCRIPTION>

With this function you can set about authorize parameters for this session.

<PARAMETERS>

Auth_type

Set the SMTP authentication type, we support five authentication methods, see below
typedef enum {

           NO_AUTH,

           LOGIN,

           PLAIN,

           CRAM_MD5,

           DIGEST_MD5,

           POP_RELAY

} AUTH_TYPE;
auth_username

           Specify username for SMTP authentication

auth_password

           Specify password for SMTP authentication

pop_port
           Specify POP server port, if SMTP AUTH is POP-Relay

        pop_server

                     Specify POP server address, if SMTP AUTH is POP-Relay

libsmtp_session

A handle returned by libsmtp_session_initialize ().

<RETURN VALUE>

Returns: 0 for success (see libsmtp_errno)

 

 

libsmtp_add_recipient

        Add the address to the recipient of this session

<SYNOPSIS>

#include < libsmtp.h>

int libsmtp_add_recipient (int libsmtp_int_rec_type, char *libsmtp_int_address,

                                      struct libsmtp_session_struct *libsmtp_session)

<DESCRIPTION>

This function will add the address to the recipient of this session. This will be added to the linked list internally.
An address must be of the RFC822-compliant type.

<PARAMETERS>

        libsmtp_int_rec_type

                     libsmtp_int_rec_type may be one of LIBSMTP_REC_TO, LIBSMTP_REC_CC, LIBSMTP_REC_BCC.

        libsmtp_int_address

                Specify the address to the recipient.

libsmtp_session

A handle returned by libsmtp_session_initialize ().

<RETURN VALUE>

Returns: 0 for success, otherwise see libsmtp_errno.

 

 

libsmtp_connect

Connect to a mail server.

<SYNOPSIS>

#include < libsmtp.h>

int libsmtp_connect (char *libsmtp_server, unsigned int libsmtp_port, int wait_timeout,

                                                      struct libsmtp_session_struct *libsmtp_session)

<DESCRIPTION>

After initial setup is done for a session, you can use this function to connect to a mail server. The string server can either be a hostname or an IP address. Port can be left at 0, then the default SMTP port (25) can be used. The libsmtp_session_struct should be initialized beforehand. Please be sure to clean up with libsmtp_free. Set a timeout limit for a connecting device that stops responding after having initiated the TCP handshake process. If an expected handshake response is not received from the connecting device in this amount of time, an error occurs.

<PARAMETERS>

libsmtp_server

Specify SMTP server address

libsmtp_port

Specify SMTP server port

wait_timeout

        Set connection handshake timeout in seconds.

        libsmtp_session

A handle returned by libsmtp_session_initialize ().

<RETURN VALUE>

A libsmtp_errno error code or 0 for success.

 

 

libsmtp_dialogue

Use this function to make libsmtp run the SMTP dialogue.

<SYNOPSIS>

#include < libsmtp.h>

int libsmtp_dialogue (struct libsmtp_session_struct *libsmtp_session)

<DESCRIPTION>

This function will handle the SMTP dialogue for you. The SMTP response minus response code can be read from the libsmtp_session->LastResponse string (which is a GString!)

<PARAMETERS>

        libsmtp_session

A handle returned by libsmtp_session_initialize ().

<RETURN VALUE>

A libsmtp_errno error code or 0 for success.

 

 

libsmtp_headers

Send the headers

<SYNOPSIS>

#include < libsmtp.h>

int libsmtp_headers (struct libsmtp_session_struct *libsmtp_session)

<DESCRIPTION>

 

<PARAMETERS>

        libsmtp_session

A handle returned by libsmtp_session_initialize ().

<RETURN VALUE>

A libsmtp_errno error code or 0 for success.

 

 

libsmtp_send_notify_message

Send the notify message

<SYNOPSIS>

#include < libsmtp.h>

int libsmtp_send_notify_message(char *message, struct libsmtp_session_struct *mailsession)

<DESCRIPTION>

Dialogue stage finishes beginning to send the content of mails. This function only send notify message, and default Content-Type is text/plain, text encoding type using 7bit code encoder.

<PARAMETERS>

        message

                specify body data

        libsmtp_session

A handle returned by libsmtp_session_initialize ().

<RETURN VALUE>

A libsmtp_errno error code or 0 for success.

 

 

libsmtp_send_bdata

Send the data of binary format

<SYNOPSIS>

#include < libsmtp.h>

int libsmtp_send_bdata(int mime_type, int mime_subtype , char *udname, char *rawdata, int size,

 struct libsmtp_session_struct *mailsession)

<DESCRIPTION>

Dialogue stage finishes beginning to send the content of mails. This function only send binary format data via memory address and support multipart type of MIME & base64 encoder.

<PARAMETERS>

        mime_type

    #define LIBSMTP_MIME_TEXT       0

    #define LIBSMTP_MIME_MESSAGE       1

    #define LIBSMTP_MIME_IMAGE   2

    #define LIBSMTP_MIME_AUDIO    3

    #define LIBSMTP_MIME_VIDEO    4

    #define LIBSMTP_MIME_APPLICATION 5

    #define LIBSMTP_MIME_MULTIPART   6

    #define LIBSMTP_MIME_CUSTOM        7

        mime_subtype         

    /* 0 to 999 are TEXT subtypes */

    #define LIBSMTP_MIME_SUB_PLAIN     0

    #define LIBSMTP_MIME_SUB_HTML    1

    #define LIBSMTP_MIME_SUB_ENGLISH        2

    #define LIBSMTP_MIME_SUB_RICHTEXT      3

    /* 1000 to 1999 are MESSAGE subtypes */

    #define LIBSMTP_MIME_SUB_RFC822  1000

    #define LIBSMTP_MIME_SUB_PARTIAL 1001

    /* 2000 to 2999 are IMAGE subtypes */

    #define LIBSMTP_MIME_SUB_GIF 2000

    #define LIBSMTP_MIME_SUB_JPG        2001

    #define LIBSMTP_MIME_SUB_PNG       2002

    #define LIBSMTP_MIME_SUB_TIFF        2003

    #define LIBSMTP_MIME_SUB_MS_BMP       2004

    #define LIBSMTP_MIME_SUB_XBITMAP       2005

    #define LIBSMTP_MIME_SUB_XPIXMAP       2006

    #define LIBSMTP_MIME_SUB_PORTABLE_ANYMAP    2007

    #define LIBSMTP_MIME_SUB_PORTABLE_BITMAP      2008

    #define LIBSMTP_MIME_SUB_PORTABLE_GRAYMAP  2009

    #define LIBSMTP_MIME_SUB_PORTABLE_PIXMAP      2010

    /* 3000 to 3999 are AUDIO subtypes */

    #define LIBSMTP_MIME_SUB_MPEGAUD     3000

    #define LIBSMTP_MIME_SUB_MIDI      3001

    #define LIBSMTP_MIME_SUB_WAV      3002

    #define LIBSMTP_MIME_SUB_AIFF       3003

    /* 4000 to 4999 are VIDEO subtypes */

    #define LIBSMTP_MIME_SUB_MPEGVID      4000

    #define LIBSMTP_MIME_SUB_MSVIDEO      4001

    #define LIBSMTP_MIME_SUB_QUICKTIME   4002

    #define LIBSMTP_MIME_SUB_FLI  4003

    /* 5000 to 5999 are APPLICATION subtypes */

    #define LIBSMTP_MIME_SUB_RTF        5000

    #define LIBSMTP_MIME_SUB_POSTSCRIPT  5001

    #define LIBSMTP_MIME_SUB_PDF        5002

    #define LIBSMTP_MIME_SUB_ZIP 5003

    #define LIBSMTP_MIME_SUB_DEBIAN_PACKAGE        5004

    #define LIBSMTP_MIME_SUB_EXECUTABLE 5005

    #define LIBSMTP_MIME_SUB_GTAR     5006

    #define LIBSMTP_MIME_SUB_SHELLSCRIPT 5007

    #define LIBSMTP_MIME_SUB_TAR        5008

    #define LIBSMTP_MIME_SUB_OCTET_STREAM   5009

    /* 6000 to 6999 are MULTIPART subtypes */

    #define LIBSMTP_MIME_SUB_MIXED   6000

    #define LIBSMTP_MIME_SUB_PARALLEL      6001

    #define LIBSMTP_MIME_SUB_DIGEST  6002

    #define LIBSMTP_MIME_SUB_ALTERNATIVE        6003

        udname

                Attached file name

        rawdata

                A pointer to a memory address which you want to send data

        size

                data size

        libsmtp_session

A handle returned by libsmtp_session_initialize ().

<RETURN VALUE>

A libsmtp_errno error code or 0 for success.

 

 

libsmtp_multipart_header

Ready to send multipart/mixed type header of MIME

<SYNOPSIS>

#include < libsmtp.h>

#include < libsmtp_mime.h>

int libsmtp_multipart_header (struct libsmtp_session_struct *mailsession)

<DESCRIPTION>

Dialogue stage finishes beginning to send the content of mails. If you want to send multipart/mixed

type of MIME, libsmtp_multipart_header() must be call it first, it will be send a complete and

standard mime parent header.

<PARAMETERS>

        libsmtp_session

A handle returned by libsmtp_session_initialize ().

<RETURN VALUE>

A libsmtp_errno error code or 0 for success.

 

 

libsmtp_send_multipart

Send content of multipart.

<SYNOPSIS>

#include < libsmtp.h>

#include < libsmtp_mime.h>

int libsmtp_send_multipart(int libsmtp_int_type, int libsmtp_int_subtype, int libsmtp_int_encoding,

                       int libsmtp_int_charset, char * udname, char *snddata, int datasize,

struct libsmtp_session_struct *mailsession)

<DESCRIPTION>

If you want to send the content of many kinds of different format or many images, you can call libsmtp_send_multipart() many times.

<PARAMETERS>

        libsmtp_int_type

Refer libsmtp_send_bdata() mime_type parameters

        libsmtp_int_subtype

Refer libsmtp_send_bdata() mime_subtype parameters

libsmtp_int_encoding

        /* Encoding types */

        #define LIBSMTP_ENC_7BIT           0

        #define LIBSMTP_ENC_BASE64      3

libsmtp_int_charset

        /* Charset values */

    #define LIBSMTP_CHARSET_NOCHARSET     -1

    #define LIBSMTP_CHARSET_USASCII     0

    #define LIBSMTP_CHARSET_ISO8859_1        1

    #define LIBSMTP_CHARSET_ISO8859_2        2

    #define LIBSMTP_CHARSET_ISO8859_3        3

udname

                Attached file name

snddata

                A pointer to a memory address which you want to send data

datasize

        Data length or size

        libsmtp_session

A handle returned by libsmtp_session_initialize ().

<RETURN VALUE>

A libsmtp_errno error code or 0 for success.

 

libsmtp_multipart_end

        Free memory the parent part of the multipart format

<SYNOPSIS>

#include < libsmtp.h>

void libsmtp_multipart_end (struct libsmtp_session_struct *libsmtp_session)

<DESCRIPTION>

When perform the libsmtp_send_multipart() completed, must call this function to free memory the parent part of the multipart format.

<PARAMETERS>

        libsmtp_session

A handle returned by libsmtp_session_initialize ().

 

libsmtp_body_end

This ends the body part

<SYNOPSIS>

#include < libsmtp.h>

int libsmtp_body_end (struct libsmtp_session_struct *libsmtp_session)

<DESCRIPTION>

This function ends the body part. It can only be used in certain stages

<PARAMETERS>

        libsmtp_session

A handle returned by libsmtp_session_initialize ().

<RETURN VALUE>

A libsmtp_errno error code or 0 for success.

 

libsmtp_quit

This ends the connection gracefully

<SYNOPSIS>

#include < libsmtp.h>

int libsmtp_quit (struct libsmtp_session_struct *libsmtp_session)

<DESCRIPTION>

This function ends the SMTP session. It can only be used in certain stages, notably in all dialogue modes.

<PARAMETERS>

        libsmtp_session

A handle returned by libsmtp_session_initialize ().

<RETURN VALUE>

A libsmtp_errno error code or 0 for success.

 

libsmtp_close

Close the SMTP connection

<SYNOPSIS>

#include < libsmtp.h>

int libsmtp_close (struct libsmtp_session_struct *libsmtp_session)

<DESCRIPTION>

This function will close the SMTP connection.

<PARAMETERS>

        libsmtp_session

A handle returned by libsmtp_session_initialize ().

<RETURN VALUE>

A libsmtp_errno error code or 0 for success.

 

libsmtp_free

        Frees the allocated session structure memory

<SYNOPSIS>

#include < libsmtp.h>

int libsmtp_free (struct libsmtp_session_struct * libsmtp_session);

<DESCRIPTION>

Use this to free the session structure. You should do this to clean up memory usage.

<PARAMETERS>

libsmtp_session

A handle returned by libsmtp_session_initialize ().

<RETURN VALUE>

Returns: 0 for success (see libsmtp_errno)

 

Client

 

Server

 
Calls Flow

 

 

 

 

 

 

 

 

 



Testing Environments

Test case 1:

        SMTP Server: smtp.pchome.com.tw

        The server support authorization: DIGEST-MD5, CRAM-MD5, PLAIN, LOGIN

        Sender: <USERACCOUNT>@pchome.com.tw
       

Step

Expected Result

Actual Result

(if different from expected)

Authentication mechanism: DIGEST-MD5

235 Authentication successful

 

Authentication mechanism: CRAM-MD5

235 Authentication successful

 

Authentication mechanism: PLAIN

235 Authentication successful

 

Authentication mechanism: LOGIN

235 Authentication successful

 

Authentication mechanism: POP_RELAY

501 Syntax error in parameter or arguments.

 

 

Test case 2:

        SMTP Server: smtp.acti.com

        The server support authorization: LOGIN

        Sender: <USERACCOUNT>@acti.com

Step

Expected Result

Actual Result

(if different from expected)

Authentication mechanism: LOGIN

235 Authentication successful

 

Authentication mechanism: DIGEST-MD5

501 Syntax error in parameter or arguments.

 

Authentication mechanism: CRAM-MD5

501 Syntax error in parameter or arguments.

 

Authentication mechanism: PLAIN

501 Syntax error in parameter or arguments.

 

Authentication mechanism: POP_RELAY

501 Syntax error in parameter or arguments.

 

 

 

 

 


Example

int main(void)

{

    unsigned char *jpegbuffer, sender[64], subject[64], notify_message[128];

    unsigned char server[64], to[64], user[64], password[64];

      char vbuff[1024*1000];

      int fd, rcv_vbuffsz, auth;

      struct libsmtp_part_struct *mutlipart;

 

    /* This struct holds all session data. You need one per mail server

       connection */

    struct libsmtp_session_struct *mailsession;

    struct libsmtp_part_struct *mainpart;

 

    sprintf(subject, "SENDMAIL: multipart test");

    strcpy(sender, "cathy.chiang@acti.com");

    strcpy(server, "smtp.acti.com");

    strcpy(user, "cathy.chiang@acti.com");

    strcpy(password, "123456");

      sprintf(to, “cathy.chiang@acti.com;cathys516@gmail.com”);

    auth = LOGIN;

    /* This mallocs the structs mem and initializes variables in it */

    mailsession = libsmtp_session_initialize();

 

      if (mailsession == NULL) {

            printf("Low memory....\n");

            return -1;

      }

 

    /* Set session environment (from address, subject) */

    if (libsmtp_set_environment (sender, subject, 0, mailsession)) {

        libsmtp_free (mailsession);

        return mailsession->ErrorCode;

    }

 

#if HAVE_AUTH

      if (libsmtp_set_authorization(auth, user, password, 110, "msa.hinet.net", mailsession)) {

        libsmtp_free (mailsession);

        return mailsession->ErrorCode;

      }

#endif

   

    /* Now we add some recipients */

    libsmtp_add_recipient (LIBSMTP_REC_TO, to, mailsession);

 

    /* This starts the SMTP connection */

    if (libsmtp_connect (server, 0, 10, mailsession)) {

        libsmtp_free (mailsession);

        return mailsession->ErrorCode;

    }

    printf ("SMTP connection running.\n");

 

    /* This will conduct the SMTP dialogue */

    if (libsmtp_dialogue (mailsession)) {

        libsmtp_free (mailsession);

        return mailsession->ErrorCode;

    }

    printf ("Dialogue finished.\n");

 

    /* Now lets send the headers - you can send your own headers too */

    if (libsmtp_headers (mailsession)) {

      libsmtp_free (mailsession);

      return mailsession->ErrorCode;

    }

 

    printf ("SMTP headers sent.\n");

 

#ifdef SEND_MIME_TEXTPLAIN

    /* This sends a line of message body */

    sprintf(notify_message, "test libsmtp_send_singlepart by cathy");

    if (libsmtp_send_notify_message(notify_message, mailsession)) {

            libsmtp_free (mailsession);

            return mailsession->ErrorCode;

    }

#endif

 

    fd = open("/var/www/images/test.jpg", O_RDWR);

    rcv_vbuffsz = read(fd, vbuff, sizeof(vbuff));

    printf(" image size = %d\n", rcv_vbuffsz);

 

#ifdef SEND_MIME_BINARY_DATA

    if (libsmtp_send_bdata(LIBSMTP_MIME_APPLICATION, LIBSMTP_MIME_SUB_ZIP, \

                                               "imagexx.jpg", vbuff, rcv_vbuffsz, mailsession)) {

        libsmtp_free (mailsession);

            return mailsession->ErrorCode;

    }

#endif

 

#ifdef SEND_MIME_MIXED

    libsmtp_multipart_header(mailsession);

    sprintf(notify_message, "test libsmtp_send_singlepart by cathy");

    libsmtp_send_multipart(LIBSMTP_MIME_TEXT, LIBSMTP_MIME_SUB_PLAIN, LIBSMTP_ENC_7BIT,

               LIBSMTP_CHARSET_USASCII,NULL,notify_message, strlen(notify_message),mailsession );

    libsmtp_send_multipart(LIBSMTP_MIME_IMAGE, LIBSMTP_MIME_SUB_JPG, LIBSMTP_ENC_BASE64,

                       LIBSMTP_CHARSET_NOCHARSET,"a.jpg",vbuff, rcv_vbuffsz,mailsession );

    libsmtp_send_multipart(LIBSMTP_MIME_IMAGE, LIBSMTP_MIME_SUB_JPG, LIBSMTP_ENC_BASE64,

                       LIBSMTP_CHARSET_NOCHARSET,"b.jpg",vbuff, rcv_vbuffsz,mailsession );

    libsmtp_send_multipart(LIBSMTP_MIME_IMAGE, LIBSMTP_MIME_SUB_JPG, LIBSMTP_ENC_BASE64,

                       LIBSMTP_CHARSET_NOCHARSET,"c.jpg",vbuff, rcv_vbuffsz,mailsession );

    Libsmtp_multipart_end(mailsession);

#endif

 

    close(fd);

 

    /* This ends the body part */

    if (libsmtp_body_end (mailsession)) {

    libsmtp_free (mailsession);

      return mailsession->ErrorCode;

    }

 

  /* This ends the connection gracefully */

    libsmtp_quit (mailsession);

  /* Free the allocated struct mem */

  libsmtp_free (mailsession);

  return 0;

}

 

Reference
http://freshmeat.net/redir/libsmtp/5725/url_homepage/libsmtp.berlios.de

http://www.linuxfromscratch.org/blfs/view/6.1/general/glib.html