ORF反垃圾邮件系统

邮件服务器-邮件系统-邮件技术论坛(BBS)

 找回密码
 会员注册
查看: 7000|回复: 2
打印 上一主题 下一主题

[原创] 邮件地址(含LotusNotes外向地址)合法性检查及别名析取、导出函数

[复制链接]
跳转到指定楼层
顶楼
发表于 2006-11-3 10:40:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#define MAILADDRoriginALIAS        0
#define MAILADDRextractALIAS    0x4000

typedef enum{
    MAILADDR_EMPTY = -1,
    MAILADDR_ERROR = 0,
    MAILADDR_NORM,
    MAILADDR_LOTUSNOTES,
    MAILADDR_UNKNOWN,
}MAILADDRTYPE;

/*
* 保存邮件地址及联系人别名的回调函数原型
**/
typedef void (*MAILADDRDIVPROC)(void *lpvoid, int type, char * alias, int num_alias, char * addr, int num_addr);


#define LOTUSNOTES_ADDR_SUPPORTED
#ifdef _WIN32
    #define QUOTATION        '\''
#else
    #define QUOTATION        '"'
#endif
#define MasCHR                'x'        /* mail address' supported character */

#ifndef SKIP_SPACE_FORWARD
    #define SKIP_SPACE_FORWARD(p)    while(' ' == *p){ ++p; }
#endif
#ifndef SKIP_SPACE_BACKWARD
    #define SKIP_SPACE_BACKWARD(p)    while(' ' == *p){ --p; }
#endif

/*
*    MasCHR表示普通字符; '@'表示只能在中间出现,且只能出现一次的字符;'.'表示分段字符
*/
#ifndef LOTUSNOTES_ADDR_SUPPORTED
    static CHAR emladdrchr[]=
//    "01234567890123456789012345678900 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
//    "01234567890123456789012345678900 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
    "################################;##^#########..#xxxxxxxxxx#;####@xxxxxxxxxxxxxxxxxxxxxxxxxx####x#xxxxxxxxxxxxxxxxxxxxxxxxxx####";
#else
    static CHAR emladdrchr[]=
    "################################;##^#########../xxxxxxxxxx#;####@xxxxxxxxxxxxxxxxxxxxxxxxxx####x#xxxxxxxxxxxxxxxxxxxxxxxxxx####";
#endif

INT xeml_address_verify(CHAR * lpszMailAddress, MAILADDRDIVPROC saveproc, void *lpvoid, BOOL fOnlyVerifyFirstOne)
{
    BYTE  * p = (unsigned char*)lpszMailAddress;
    INT        iNormAddrCount = 0L, iLotusNotesCount = 0L;
   
    if(NULL == lpszMailAddress){
        return MAILADDR_ERROR;
    }else{
        SKIP_SPACE_FORWARD(p);
        if('\0' == *p){
            return MAILADDR_EMPTY;
        }
    }
    while(*p){
        CHAR  * alias_begin = NULL;        /* first quotation if address includes alias */
        CHAR  * alias_end    = NULL;
        CHAR  * virgule = NULL;            /* first virgule mark in LotusNotes' address */
        CHAR  * p_start    = NULL;            /* first character of a real mail address */
        CHAR  * p_tail    = NULL;
        CHAR  * p_chrAt    = 0L;            /* position of character '@' in a mail address */
        INT        iDotCount = 0L;
        
        SKIP_SPACE_FORWARD(p);

        if(QUOTATION == *p){            /* seek alias from "alias" <accountname@isp.com.org>,  no space between braces */
            alias_begin = ++p;
            if(NULL == (p_start = strchr(alias_begin, QUOTATION))){
                return MAILADDR_ERROR;    /* isn't a brace of double-quotation-mark */
            }else{
                alias_end = p_start++;    /* jump to the first character after right double-quotation-mark */
            }
            SKIP_SPACE_FORWARD(p_start);
            
            if('<' == *p_start) { p = ++p_start; }
            else{
                return MAILADDR_ERROR;
            }
        }

        for(p_tail = NULL, p_start = p;  *p;  ++p){
            if(*p>127){ return MAILADDR_ERROR; }
            switch(emladdrchr[*p]) {
#ifdef LOTUSNOTES_ADDR_SUPPORTED
            case '/':    /* Lotus Notes' address is like "user/sub-group/.../group@domain" */
                        if(p==p_start || MasCHR != emladdrchr[*(p-1)]){ return MAILADDR_ERROR; }
                        if(NULL == virgule)    { virgule = p; }
                        if(NULL != p_chrAt)    { return MAILADDR_ERROR; }
                        break;
#endif
            case '@':    if(p==p_start || MasCHR != emladdrchr[*(p-1)]){ return MAILADDR_ERROR; }
                        if(NULL == p_chrAt){
                            p_chrAt = p;
                        }else{
                            return MAILADDR_ERROR;
                        }
                        break;
            case '.':    if(p==p_start || MasCHR != emladdrchr[*(p - 1)])/* it's dot or minus mark */
                            return MAILADDR_ERROR;                        /* error format like ab..cd, or ab.-cd */
                        if(NULL != p_chrAt && '.' == *p){ iDotCount++; }
                        break;
            case ';':    p_tail=p;    break;
            case MasCHR:break;
            default:    if(NULL != alias_end && *p=='>'){ p_tail=p++;  break; }else{ return MAILADDR_ERROR; }
            }
            if(NULL != p_tail){ break; }
        }
        SKIP_SPACE_FORWARD(p);

        if(';' == *p){
            ++p;
        }else if('\0' != *p){
            return MAILADDR_ERROR;
        }
        if(NULL == virgule){            /* It's a normal mail address such as " 'mary'<abc@edu.cn>" */
            if(NULL == p_chrAt){
                return MAILADDR_ERROR;
            }
            if(iDotCount <= 0){            /* must include '.' in a mail address ? */
                return MAILADDR_ERROR;
            }
            ++iNormAddrCount;
        }else{                            /* LotusNotes address, but the address like "abcd/bb/cc" is valid ? */
            ++iLotusNotesCount;
        }
        if(NULL != saveproc && NULL != lpvoid){
            INT     iAlias = 0;
            INT     iAddr = 0;

            if(NULL == alias_end){        /* no alias in this address */
                alias_begin = p_start;    iAlias = (NULL==virgule ? p_chrAt : virgule) - alias_begin;
            }else{
                iAlias = alias_end - alias_begin;
            }
            iAddr = p_tail - p_start;

            saveproc(lpvoid,
                (NULL == virgule ? MAILADDR_NORM : MAILADDR_LOTUSNOTES) | (NULL == alias_end ? MAILADDRextractALIAS : 0),
                alias_begin, iAlias, p_start, iAddr);
        }
        if(fOnlyVerifyFirstOne){
            break;
        }
        SKIP_SPACE_FORWARD(p);
    }
    if(iNormAddrCount > 0 || iLotusNotesCount > 0){
        return (iLotusNotesCount > 0) ? MAILADDR_LOTUSNOTES : MAILADDR_NORM;
    }else{
        return MAILADDR_ERROR;
    }
}
沙发
发表于 2006-11-3 13:58:57 | 只看该作者
看不明白,怎么用?用到哪?
藤椅
 楼主| 发表于 2006-11-3 18:04:01 | 只看该作者

邮件地址合法性检查及别名析取、导出函数(续)

用法简介:
1、xeml_address_verify(lpszAddress, NULL, NULL,FALSE),判断整个邮件地址是否合法;当输入参数为TRUE时,只判断第一个邮件地址是否合法
  eg. xeml_address_verify(" \"mary\"<abc@bb.com>; henry/mobile/leopard@com;", NULL, NULL, TRUE),只判断第一个地址abc@bb.cc是否合法
2、回调函数
  简单示例( 假定lpvoid是一个数组)
    void mail_save_alias(void *lpvoid, int type, char * alias, int num_alias, char * addr, int num_addr)
    {
        char * p = (char*)lpvoid;
       if(p && addr && num_addr>0){
            strcpy(p, addr);
        }
    }
   当然,可以实现得完美些,比如lpvoid是一个链表,则可以用一个struct来存储地址分解之后的细节

  调用:
  xeml_address_verify(" \"mary\"<abc@bb.com>; henry/mobile/leopard@com;", mail_save_detail, (void*)outstr, TRUE)

3、起初我们用正则表达式解析和判断地址的合法性,但是速度比较慢(子表达式太多),没有办法时,只好自己写了。自己觉得用得还行,各位大家不要见笑 ^_^

[ 本帖最后由 hylaking 于 2006-11-3 18:15 编辑 ]
您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

小黑屋|手机版|Archiver|邮件技术资讯网

GMT+8, 2024-5-14 20:41

Powered by Discuz! X3.2

© 2001-2016 Comsenz Inc.

本论坛为非盈利中立机构,所有言论属发表者个人意见,不代表本论坛立场。内容所涉及版权和法律相关事宜请参考各自所有者的条款。
如认定侵犯了您权利,请联系我们。本论坛原创内容请联系后再行转载并务必保留我站信息。此声明修改不另行通知,保留最终解释权。
*本论坛会员专属QQ群:邮件技术资讯网会员QQ群
*本论坛会员备用QQ群:邮件技术资讯网备用群

快速回复 返回顶部 返回列表