MIME Message Composer/Analyser

219 篇文章 ¥19.90 ¥99.00
这是一个用ANSI C++编写的MIME组件,旨在简化MIME合规应用的开发,提供对标准和自定义编码的支持。它可以创建复杂的邮件消息,包括文本部分、附件、嵌套消息,并具有头字段编码、折叠及解码功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Introduction

This implementation is designed to provide an easy-to-use, well-encapsulated component for the development of MIME-conformant applications, with less MIME knowledge. However, because MIME is open and extensible, to provide an easy way to support any customized extension is also important. Here are some features of this implementation:

  • Meet the requirements of MIME-conformance.
  • Written in ANSI C++, easy to migrate to UNIX.
  • Full control on all (standard and extended) header fields and body parts. Provide wrappers on raw data to interpret the standard fields.
  • Provide standard encoding mechanism (Quoted-Printable and Base64) and support all the standard media types.
  • Seamless interface to support extended media types and encoding mechanisms.
  • Provide standard header encoding/decoding for non-ASCII text, and folding/unfolding for long line text.

Using the code

Although there're more than 10 classes in the source files, the only 3 or 4 classes you need to work with, include:

CMimeEnvironmentThe global environment to manage encoding mechanisms and options.
CMimeFieldRepresents a field of a MIME body part header. Provides methods to manage the name, value, parameters and charset of the field.
CMimeBodyRepresents a body part of a MIME message. It's derived from CMimeHeader class, provides methods to manage the content and header fields of the body part.
CMimeMessageRepresents a MIME message. It's derived from CMimeBody class, provides extra functionality to access RFC822 message header fields (e.g. From, To, Date, Subject).

Compose a message

This example demonstrates how to create a complex multipart message with a text part, a file attachment, an attached message, and an embedded multipart entity.

Collapse Copy Code
    CMimeMessage mail;

    // Initialize message header
    mail.SetDate(); // set 'Date' field to the current time
    mail.Setversion();
    mail.SetFrom("sender@local.com");
    mail.SetTo("recipient1@server1.com, 
      Nick Name <recipient2@server1.com>, 
      /"Nick Name/" <recipient3@server3.com>");
    mail.SetCc("recipient4@server4.com");
    mail.SetSubject("Test message");
    mail.SetFieldValue("X-Priority", "3 (Normal)"); // extended field
    mail.SetFieldValue("X-My-Field", "My value");   // user-defined field

    // Initialize body part header
    mail.SetContentType("multipart/mixed");
    // generate a boundary delimeter automatically
    // if the parameter is NULL
    mail.SetBoundary(NULL);

    // Add a text body part
    // Content-Type is not specified, so the default
    // value "text/plain" is implicitly used
    // Content-Transfer-Encoding is not specified
    // so the default value "7bit" is implicitly used
    CMimeBody* pBp = mail.CreatePart();
    pBp->SetText("Hi, there");  // set the content of the body part

    // Add a file attachment body part
    pBp = mail.CreatePart();
    pBp->SetContentDescription("enclosed photo");
    pBp->SetTransferEncoding("base64");
    // if Content-Type is not specified, it'll be
    // set to "image/jpeg" by ReadFromFile()
    pBP->ReadFromFile("d://myphoto.jpg"); 

    // Generate a simple message
    CMimeMessage mail2;
    mail2.SetFrom("abc@abc.com");
    mail2.SetTo("abc@abc.com");
    mail2.SetSubject("This is an attached message");
    mail2.SetText("Content of attached message./r/n");

    // Attach the message
    pBp = mail.CreatePart();
    pBp->SetContentDescription("enclosed message");
    pBp->SetTransferEncoding("7bit");
    // if Content-Type is not specified, it'll be
    // set to "message/rfc822" by SetMessage()
    pBp->SetMessage(&mail2); 

    // Add an embeded multipart
    pBp = mail.CreatePart();
    pBp->SetContentType("multipart/alternative");
    pBp->SetBoundary("embeded_multipart_boundary");
    CMimeBody *pBpChild = pBp->CreatePart();
    pBpChild->SetText("Content of Part 1/r/n");
    pBpChild = pBp->CreatePart();
    pBpChild->SetText("Content of Part 2/r/n");

    // Store the message to buffer    
    // fold the long lines in the headers
    CMimeEnvironment::SetAutoFolding(true); 
    int nSize = mail.GetLength();
    char* pBuff = new char[nSize];
    nSize = mail.Store(pBuff, nSize);
    ...
    delete pBuff;

Analyze a message

To analyze a message is the same and simple: call Load() to load the message object from buffer, then call FindFirstPart()/FindNextPart() functions to iterate its child body parts. But the fact that a multipart entity could have embedded multipart entities brings some complexities. We have to call FindFirstPart()/FindNextPart() on each child body part recursively to iterate all the descendant parts. So CMimeBody class provides an alternative way, to retrieve a list of all the descendant body parts, by calling GetBodyPartList().

Collapse Copy Code
    CMimeMessage mail;
    int nLoadedSize = mail.Load(pBuff, nDataSize);

    // Analyze the message header
    const char* pszField;
    pszField = mail.GetSubject();
    if (pszField != NULL)
        printf("Subject: %s/r/n", pszField);
    pszField = mail.GetFrom();
    if (pszField != NULL)
        printf("From: %s/r/n", pszField);
    pszField = mail.GetFieldValue("X-Priority");
    if (pszField != NULL)
        printf("X-Priority: %s/r/n", pszField);

    // Iterate all the descendant body parts
    CMimeBody::CBodyList bodies;
    int nCount = mail.GetBodyPartList(bodies);
    CMimeBody::CBodyList::const_iterator it;
    for (it=bodies.begin(); it!=bodies.end(); it++)
    {
        CMimeBody* pBP = *it;

        // Iterate all the header fields of this body part:
        CMimeHeader::CFieldList& fds = pBP->Fields();
        CMimeHeader::CFieldList::const_iterator itfd;
        for (itfd=fds.begin(); itfd!=fds.end(); itfd++)
        {
            const CMimeField& fd = *itfd;
            printf("%s: %s/r/n", fd.GetName(), fd.GetValue());
        }

        if (pBP->IsText())
        {
            string strText;
            pBP->GetText(strText);
            printf("Content: %s/r/n", strText.c_str());
        }
        else if (pBP->IsAttachment())
        {
            string strName = pBP->GetName();
            printf("File name: %s/r/n", strName.c_str());
            printf("File size: %d/r/n", pBP->GetContentLength());
            strName = "d://download//" + strName;
            pBP->WriteToFile(strName.c_str());
        }
    }

Header encoding and folding

The header encoding is to encode any non-ASCII text data in message headers to 'encoded-word'. For example, a field like "Subject: Bonne Année" will be encoded to "Subject: =?iso-8859-1?Q?Bonne=20Ann=E9e?=" and "From: René <sender@local.com>" will be encoded to "From: =?iso-8859-1?Q?Ren=E9?= <sender@local.com>".

During the period of storing (invoking CMimeBody::Store() function), the header encoding is performed automatically if a field contains non-ASCII text, and the 'charset' of this field has been specified. The 'charset' of a field can be specified by calling CMimeBody::SetFieldCharset(), or by passing a charset string to functions like CMimeBody::SetFieldValue(), CMimeMessage::SetSubject(), CMimeMessage::SetFrom(), etc.

Instead of specifying charset for each field repeatedly, you can specify the 'global charset' by calling CMimeEnvironment::SetGlobalCharset(). When the header encoding is being performed, the global charset is used if the field's charset is empty. If the global charset is empty too, the header encoding doesn't occur. So you can leave both charsets empty if you don't need the header encoding.

Collapse Copy Code
    mail.SetSubject("Bonne Année", "iso-8859-1");
    or:
    mail.SetFieldValue("Content-Description", "carte bonne année");
    CMimeEnvironment::SetGlobalCharset("iso-8859-1");

Furthermore, header folding is performed automatically too. In general, any header lines longer than 76 bytes will be folded by inserting "/r/n/t" at the position of a space (SPACE or TAB). For address fields (such as From, To, CC, etc.), the folding occurs between addresses, after the separating comma. However, the header folding can be turned on/off by calling CMimeEnvironment::SetAutoFolding() function with bAutoFolding parameter set to true/false.

Support of custom encoding

To support any Content-Transfer-Encoding mechanisms other than Quoted-Printable and Base64, derive a class from CMimeCodeBase, then register this class by invoking REGISTER_MIMECODER().

Collapse Copy Code
class CMyCoder : public CMimeCodeBase
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值