邮件Socket IO实现 - 参考libESMTP

关于libESMTP
            libESMTP, version 1.0
                  -- oOo --
            Brian Stafford  <brian@stafford.uklinux.net>

之前我自己也写过一个简单的Socket IO操作封装,主要目标是实现一个循环列表,把socket fd封装起来,通过这个循环列表建立它的输入缓冲。数据结构的定义为:
#define KAPOK_FILE_BUF_LEN  1024

typedef struct
{
    int kapok_file_magic;
    int el_flag;
    int fd;
    int read_head, read_tail;
    int fd_status;
    unsigned char read_buf[KAPOK_FILE_BUF_LEN];

} KapokFile;

enum
{
    KF_STATUS_OK,
    KF_STATUS_EOF,      //一般来说不应该有这个状态,因为socket没有eof的概念
    KF_STATUS_INVALID
};

而libESMTP提供的sio数据结构(及算法)就复杂很多了。查看siobuf.h可以看到它的所有外露接口:

#define SIO_BUFSIZE 2048 /* arbitrary, not too short, not too long */
#define SIO_READ    1
#define SIO_WRITE   2

typedef void (*recodecb_t) (char **dstbuf, int *dstlen,
                const char *srcbuf, int srclen, void *arg);
typedef void (*monitorcb_t) (const char *buffer, int length, int direction,
                 void *arg);

struct siobuf *sio_attach(int sdr, int sdw, int buffer_size);
void sio_detach(struct siobuf *sio);
void sio_set_monitorcb(struct siobuf *sio, monitorcb_t cb, void *arg);
void sio_set_timeout(struct siobuf *sio, int milliseconds);
void sio_set_securitycb(struct siobuf *sio, recodecb_t encode_cb,
                recodecb_t decode_cb, void *arg);
int sio_poll(struct siobuf *sio,int want_read, int want_write, int fast);
void sio_write(struct siobuf *sio, const void *bufp, int buflen);
void sio_flush(struct siobuf *sio);
void sio_mark(struct siobuf *sio);
int sio_fill(struct siobuf *sio);
int sio_read(struct siobuf *sio, void *bufp, int buflen);
char *sio_gets(struct siobuf *sio, char buf[], int buflen);
int sio_printf(struct siobuf *sio, const char *format, ...)
           __attribute__ ((format (printf, 2, 3))) ;
void *sio_set_userdata (struct siobuf *sio, void *user_data);
void *sio_get_userdata (struct siobuf *io);


#ifdef USE_TLS
int sio_set_tlsclient_ssl (struct siobuf *sio, SSL *ssl);
int sio_set_tlsserver_ssl (struct siobuf *sio, SSL *ssl);
#endif

1. attach/detach
用来关联和去关联socket套接字到SIO数据结构,这个过程中,套接字并没有被关闭。我设计的数据结构就只提供KapokFile的创建(关联)和关闭,在关闭时,套接字也会被关闭。从某个角度来说,我的设计参考了FILE数据结构的实现。

2. timeout设置
我的实现在timeout是在每次get/put中通过显式参数输入的。这里把timeout做到数据结构中。sio的timeout使用poll实现,而我原来的设计采用了select为实现,道理是一样的。

3. monitor call back
一个有利于调试的选项

4. security/recode call back
一个编码转译扩展接口,可以把邮件内容进行加密传送。

5. poll
对SIO数据结构的poll接口封装。查看源代码可以看到它支持SSL,而且利用SIO提供的读缓冲区,可以快速返回数据,提高处理效率。

6. write/flush/mark
写相关的函数,flush是真正的写,mark可以用来设置一个flush_mark的位置标置。如果flush_mark存在,则flush的目标不是整个有效缓冲区,而是flush以flush_mark指定的邮件。
write就是典型的套接字缓冲读写实现。配套实现有raw_write()函数

7. read/fill
fill和flush有点相似

8. gets/printf
高级点的读写操作

整体而言,SIO和我设计的KapokFile的区别有下面几点:

1.加入了monitor call back,支持联机monitor
2.加入recode call back,支持SSL等加密方式
3. 采用memmove则不是环循一维表的方式来处理内存
4. 提供flush_mark,而不是全面flush(觉得实用性不大)
5. 采用attach/detach来管理套接字关联,更加灵活。不过我的实现也可以接受。
6. 我没有把write_buf加入到数据结构中去。

还有一点就是sio采用双描述字,分别表示读和写。



因工作需要在Linux环境中用C++编写个发送邮件的程序,着实费了点周折,最终得以满意解决,现将历程与成果与大家分享! 一、刚开始网上一通逛搜,发现Linux环境下,发邮件使用较多的方法是libesmtp包,网上也有示例,按照相关章的指引,很容易就实现邮件的发送,但问题是不知道如何实现SSL。 二、发现libesmtp文件中有个smtp_starttls_set_ctx接口,似乎是可以解决ssl问题的,逛搜libesmtp解决SSL发送邮件的解决办法,几乎无任何信息,后来下载了个libesmtp的源代码包libesmtp-1.0.6.tar.bz2,内含examples示例目录,可以直接编译成功,但似乎是只支持tls邮件发送,而不支持ssl邮件的发送,百思不得其解。 三、接着寻找别的解决办法,在CSDN搜到一个csmtp说可以解决SSL邮件发送问题的资源,但下载需要50积分,说心里话能解决问题50积分也是值得的,但没有呀,提供资源者还比较仁义,告知资来源于https://www.codeproject.com,于是乎在codeproject找到了csmtp的资源,有两个版本,v2.4版本包CSmtp_v2_4_ssl.zip,v1.8版本分为window(CSmtp_v1_8a.zip)和linux(CSmtp_v1_8b.zip)两个包。 四、为了能省点精力,就直接用版较低的linux版吧,解压后发现有makefile文件,可直接编译通过,一般的邮件能发送成功,但可惜的是v1.8版本也不支持ssl协议。 五、其实从包的名字上就能看出来v2.4版本开始支持 ssl协议,但v2.4并不分windows版本和linux版本,是否能支持linux呢,查看源代码发现有对linux的支持,只是包内没有makefile文件,似乎没有在linux目录下编译过,于是编写了个makefile文件尝试编译,竞然编通过,而且发送文件成功,经过测试可以支持ssl邮件的发送,因暂无需求tls未做测试。 六、现将程序重新打包成csmtp_v2.4_linux.tar文件,与大家分享,文中所提到的相关资源包都一并打包到资源中了。 最后感谢原创christopher w. backen提供的代码资源!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值