/*
 *
 * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
 *
 *  All rights reserved.
 */

#ifndef __IMTA_H
#define __IMTA_H

#include <sys/types.h>
#include <time.h>
#include "rfc822.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef XP_WIN32
//#define  PTHREAD_MUTEX_INITIALIZER       {0, 0, 0}  /* TODO FIX */
#endif

/* Message delivery statusses */
typedef enum {
  IM_DLVSTAT_DEFERRED    = 1,
  IM_DLVSTAT_DELIVERED   = 2,
  IM_DLVSTAT_FAILED      = 3,
  IM_DLVSTAT_FORWARDED   = 4,
  IM_DLVSTAT_DELAYED     = 1,
  IM_DLVSTAT_BOUNCED     = 6,
  IM_DLVSTAT_TIMEDOUT    = 7,
  IM_DLVSTAT_READ        = 4
} im_dlv_stat_t;

/* Recipient dispositions */
typedef enum {
  IM_DISP_DEFERRED          = 1,
  IM_DISP_DELIVERED         = 2,
  IM_DISP_FAILED            = 3,
  IM_DISP_RELAYED           = 4,
  IM_DISP_RELAYED_FOREIGN   = 5,
  IM_DISP_RETURN            = 6,
  IM_DISP_TIMEDOUT          = 7
} im_disp_t;

/* Notary parameters */
#define NOTARY_HEADER                              1
#define NOTARY_NOHEADER                            2
#define IM_NOTIFY_FAILURE                          4
#define IM_NOTIFY_SUCCESS                          8
#define IM_NOTIFY_DELAY                           16
#define IM_NOTIFY_GENERATE                        32
#define IM_NOTIFY_NEVER                           64

/* recipient types */
#define IM_RCPT_ENV                                1
#define IM_RCPT_TO                                 2
#define IM_RCPT_CC                                 4
#define IM_RCPT_BCC                                8

/* debug types */
#define IM_DEBUG_ENQUEUE                           1
#define IM_DEBUG_DEQUEUE                           2

/* counters types */
typedef enum {
  IMCTR_DELIVERED_MSGS                    = 10,
  IMCTR_SUBMITTED_MSGS                    = 11,
  IMCTR_STORED_MSGS                       = 12,
  IMCTR_RECEIVED_MSGS                     = 13,
  IMCTR_REJECTED_MSGS                     = 14,
  IMCTR_ATTEMPTED_MSGS                    = 15,
  IMCTR_FAILED_MSGS                       = 16,
  IMCTR_DELIVERED_VOLUME                  = 20,
  IMCTR_SUBMITTED_VOLUME                  = 21,
  IMCTR_STORED_VOLUME                     = 22,
  IMCTR_RECEIVED_VOLUME                   = 23,
  IMCTR_REJECTED_VOLUME                   = 24,
  IMCTR_ATTEMPTED_VOLUME                  = 25,
  IMCTR_FAILED_VOLUME                     = 26,
  IMCTR_DELIVERED_RCPTS                   = 30,
  IMCTR_SUBMITTED_RCPTS                   = 31,
  IMCTR_STORED_RCPTS                      = 32,
  IMCTR_RECEIVED_RCPTS                    = 33,
  IMCTR_REJECTED_RCPTS                    = 34,
  IMCTR_ATTEMPTED_RCPTS                   = 35,
  IMCTR_FAILED_RCPTS                      = 36,
  IMCTR_TOTAL_ATTEMPTS			  = 40,
  IMCTR_FIRST_ATTEMPTS			  = 41,
  IMCTR_SUCCESSFUL_FIRST_ATTEMPTS	  = 42,
  IMCTR_UNATTEMPTED_QUEUE_TIME		  = 50,
  IMCTR_QUEUE_TIME			  = 51
} imctr_type_t;

/* return codes for immd_mime_decode */
#define IMTARC_OK          0x0A9C801B /* Successful, normal completion */
#define IMTARC_EOF         0x0A9C8102 /* End of file */
  
/* return codes */
#define IMRC_OK                                    0
#define IMRC_EOF                                   1

#define IMRC_INVALID_ADDRESS                     -10
#define IMRC_ADDRESS_TOO_LONG                    -11
#define IMRC_NO_RECIPIENT                        -12
#define IMRC_NOT_AUTHORIZED                      -13
#define IMRC_TEXT_TRUNCATED                      -14
#define IMRC_NO_MAILFROM                         -15
#define IMRC_UNKNOWN_USER                        -16
#define IMRC_INVALID_DATE                        -17

#define IMRC_INVALID_NOTARY_FLAGS                -20
#define IMRC_INVALID_RECIPIENT_TYPE              -21
#define IMRC_CHANNEL_NAME_TOO_LONG               -22
#define IMRC_INVALID_CHANNEL_NAME                -23
#define IMRC_INVALID_DELIVERY_STATUS             -24
#define IMRC_INVALID_COUNTER_TYPE                -25
#define IMRC_INVALID_RECIPIENT_DISPOSITION       -26

#define IMRC_OUT_OF_MEMORY                       -31
#define IMRC_INSUFFICIENT_PRIVILEGES             -32
#define IMRC_OUT_OF_DISK_SPACE                   -33
#define IMRC_CONFIG_MISMATCH                     -34
#define IMRC_MESSAGE_CORRUPTED                   -35
#define IMRC_MESSAGE_LOCKED                      -36
#define IMRC_LOCK_ERROR                          -37
#define IMRC_ALREADY_INITIALIZED                 -38

#define IMRC_BAD_CONTEXT                         -40
#define IMRC_NO_ENVELOPE                         -41
#define IMRC_ENVELOPE_NOT_READ                   -42
#define IMRC_BODY_NOT_READ                       -43
#define IMRC_NO_MESSAGE                          -44
#define IMRC_HDR_READ                            -45
#define IMRC_INVALID_RECIPIENT                   -46

/* fixed length strings */
#define IM_CHANNEL_LEN                            32
#define IM_LOG_LEN                              1024
#define IM_DATE_LEN                              256

/* delivery flags returned by immd_get_recipient_delivery_flags */
#if !defined(PMDF_DFLAGS_SIEVEFILEINTO)
#define PMDF_DFLAGS_SIEVEFILEINTO 0x00000001
#define PMDF_DFLAGS_QUOTABYPASS   0x00000002
#define PMDF_DFLAGS_DOTSTUFF      0x00000004
#endif

/*
 * Data types definitions.
 */
typedef struct im_md_s  *immd_t;
typedef struct im_me_s  *imme_t;
typedef struct im_ctr_s *imctr_t;


/* 
 * Prototypes
 */

/*
 * Message enqueue API
 */
void imme_abort(imme_t e);
int  imme_add_recipient(imme_t e, int rcpt_type, int flags,
			const char *rcpt, const char *orcpt);
int  imme_copy(imme_t e, immd_t d);
int  imme_write_header(imme_t e, imhdr_t hdr);
int  imme_start_envelope(imme_t e, const char *from);
int  imme_init(imme_t *e);
void imme_end(imme_t e);
int  imme_write_text(imme_t e, const char *line);
int  imme_enqueue(imme_t e);


/*
 * Message dequeue API
 */

/* create a dequeue context */
int  immd_init(immd_t *d);

/* destroy a dequeue context */
void immd_end(immd_t d);

/* get next message from the queue */
int  immd_get_message(immd_t d, const char **from, int *size);
int  immd_wait_message(immd_t d, const char **from, int *size, int timeout);

/* dequeue current message from the queue, process deferrals and failures */
int  immd_dequeue(immd_t d);

/* defer current message for all the recipients */
int  immd_defer(immd_t d, int log_it, const char *reason);

/* get next message recipient */
int  immd_get_recipient(immd_t d, int *flags,
			const char **rcpt, const char **orcpt);

int  immd_rewind_recipients(immd_t d);

/* get the delivery flags (!= notary) for the recipient just read.
 * may be called just after immd_get_recipient */
int  immd_get_recipient_delivery_flags(immd_t d, int *dflags);

int  immd_get_recipient_directory_info(immd_t md, char *disk_quota,
				       char *message_quota, char *addflag,
				       void *spare2, void *spare3);

int  immd_get_recipient_intermediate(immd_t md, char **ircpt);

int  immd_read_failure_log(immd_t d, const char **date, const char **reason);
int  immd_read_header(immd_t d, imhdr_t *h);
int  immd_read_text(immd_t d, char **text);

/* get the entire message map and length */
int  immd_get_message_handle(immd_t md, char **text, size_t *len);

int  immd_recipient_disposition(immd_t d,
				const char *rcpt,
				const char *orcpt, 
				const char *reason,
				im_disp_t action);

/* same as immd_recipient_disposition but also accepts an rfc1893
 * Enhanced Mail System Status Code */
int  immd_recipient_disposition2(immd_t d,
				 const char *rcpt,
				 const char *orcpt, 
				 const char *reason,
				 im_disp_t action,
				 int estatus[3]);

/* set a non-default backoff period for a deferred message */
int  immd_backoffOverride(immd_t d, int seconds);

int  immd_rewind(immd_t d);
const char *immd_get_channel(immd_t d);
void *immd_get_recipient_data(immd_t d);
void immd_set_recipient_data(immd_t d, void *data);
int  immd_mime_decode(immd_t d, void *param,
		      int (*output_header)(void *, imhdr_t, int, int, int),
		      int (*output_line)(void *, const char *, int),
		      int (*output_block)(void *, const char *, int));


/*
 * IMTA management API
 */
int  imta_init(const char *channel);
void imta_end(void);
const char* imta_get_channel();
void imta_set_debug(int mode);
void imta_debug(const char *msg, ...);
const char *imta_error(int err);

int  imctr_load(imctr_t *ctr, const char *channel);
int  imctr_get(imctr_t ctr, int index, imctr_type_t counter,
	       const char **channel);
void imctr_free(imctr_t ctr);

void imta_get_date(char *date, time_t t);
int  imta_parse_date(char *date, struct tm *tm);
const char *imta_get_hostname();

#ifdef __cplusplus
	   }
#endif

#endif  /* __IMTA_H */
