Mimetic

LifeMotif: GMail-based Private Diary System에 필요한 이메일 파서 라이브러리.

Mimetic에서 제공하는 상당량에 대한 필드 파싱 정보에 대한 예제 코드

mimetic_snippets.cpp
#include <iostream>
#include <sstream>
#include <iterator>
#include <fstream>
#include <iterator>
#include <string>
#include <algorithm>
#include <mimetic/mimetic.h>
 
void read(const std::string& filename, std::string& content)
{
    if (content.empty() == false) {
        std::string().swap(content);
    }
 
    std::ifstream ifs;
    ifs.open(filename);
 
    while ( ifs.good() ) {
        char c = ifs.get();
        if (ifs.good()) content.push_back(c);
    }
}
 
void print_param_header(const std::string& param_name)
{
    std::cout << "[";
    std::cout << param_name;
    std::cout << "]\n";
}
 
void print_param_footer()
{
    std::cout << '\n';
}
 
void parse_mailbox(const mimetic::Mailbox& mb)
{
    const std::string mailbox = mb.mailbox();
    const std::string domain = mb.domain();
    const std::string label = mb.label();
    const std::string sourceroute = mb.sourceroute();
    const std::string str = mb.str();
 
    std::cout << "mailbox:     " << mailbox << '\n';
    std::cout << "domain:      " << domain << '\n';
    std::cout << "label:       " << label << '\n';
    std::cout << "sourceroute: " << sourceroute  << '\n';
    std::cout << "str:         " << str << '\n';
}
 
void parse_mailbox_list(const mimetic::MailboxList& mblist)
{
    mimetic::MailboxList::const_iterator it;
    for(it = mblist.begin(); it != mblist.end(); ++it) {
        const mimetic::MailboxList::value_type& v = *it;
        parse_mailbox(v);
    }
}
 
void parse_group(const mimetic::Group& group)
{
    print_param_header("group");
    std::cout << "group: " << group.name() << std::endl;
    print_param_footer();
}
 
void parse_address(const mimetic::Address & adr)
{
    const mimetic::Mailbox& mailbox = adr.mailbox();
    const mimetic::Group&   group = adr.group();
    bool isGroup = adr.isGroup();
 
    parse_mailbox(mailbox);
    std::cout << "isGroup: " << isGroup << std::endl;
    parse_group(group);
}
 
void parse_address_list(const mimetic::AddressList& adrList)
{
    mimetic::AddressList::const_iterator it;
    for(it = adrList.begin(); it != adrList.end(); ++it) {
        const mimetic::Address& adr = *it;
        parse_address(adr);
    }
}
 
void parse_mime_version(const mimetic::MimeVersion &mimeVersion)
{
    std::cout << mimeVersion.str() << std::endl;
}
 
void parse_messageid(const mimetic::MessageId& messageid)
{
    std::cout << messageid.str() << std::endl;
}
 
void parse_field_param(const mimetic::FieldParam& param)
{
    std::cout << "name/value: " << param << std::endl;
 
    const std::string& name = param.name();
    const std::string& value = param.value();
 
    std::cout << "  name:  " << name << std::endl;
    std::cout << "  value: " << value << std::endl;
}
 
void parse_content_type(const mimetic::ContentType& contentType)
{
    const std::string             &type        = contentType.type();
    const std::string             &subtype     = contentType.subtype();
    bool                           isMultipart = contentType.isMultipart();
    const mimetic::FieldParamList &paramList   = contentType.paramList();
 
    std::cout << "type:    "     << type << '\n';
    std::cout << "subtype: "     << subtype <<'\n';
    std::cout << "isMultipart: " << isMultipart << '\n';
 
    mimetic::FieldParamList::const_iterator it;
    for(it = paramList.begin(); it != paramList.end(); ++it) {
        const mimetic::FieldParam& param = *it;
        parse_field_param(param);
    }
}
 
void parse_content_transfer_encoding(const mimetic::ContentTransferEncoding &content_transfer_encoding)
{
    const std::string& mechanism = content_transfer_encoding.mechanism();
 
    std::cout << "mechanism: " << mechanism << std::endl;
}
 
void parse_content_disposition(const mimetic::ContentDisposition &content_disposition)
{
    const std::string             &type        = content_disposition.type();
    const mimetic::FieldParamList &paramList   = content_disposition.paramList();
 
    std::cout << "type:    "     << type << '\n';
 
    mimetic::FieldParamList::const_iterator it;
    for(it = paramList.begin(); it != paramList.end(); ++it) {
        const mimetic::FieldParam& param = *it;
        parse_field_param(param);
    }
}
 
void parse_content_description(const mimetic::ContentDescription &content_description)
{
    std::cout << content_description.str() << std::endl;
}
 
void parse_content_id(const mimetic::ContentId &content_id)
{
    std::cout << content_id.str() << std::endl;
}
 
void parse_Rfc822_header(const mimetic::Rfc822Header& header)
{
    // Rfc822Header class
    const mimetic::Mailbox     &sender  = header.sender();
    const mimetic::MailboxList &from    = header.from();
    const mimetic::AddressList &to      = header.to();
    const std::string          &subject = header.subject();
    const mimetic::AddressList &replyto = header.replyto();
    const mimetic::AddressList &cc      = header.cc();
    const mimetic::AddressList &bcc     = header.bcc();
    const mimetic::MessageId   &msgid   = header.messageid();
 
    if (header.hasField("Content-Type")) {
        std::cout << header.field("Content-Type") << std::endl;
    }
 
    // Rfc822Header class
    print_param_header("sender");
    parse_mailbox(sender);
    print_param_footer();
 
    print_param_header("from");
    parse_mailbox_list(from);
    print_param_footer();
 
    print_param_header("to");
    parse_address_list(to);
    print_param_footer();
 
    print_param_header("subject");
    std::cout << subject << std::endl;
    print_param_footer();
 
    print_param_header("replyto");
    parse_address_list(replyto);
    print_param_footer();
 
    print_param_header("cc");
    parse_address_list(cc);
    print_param_footer();
 
    print_param_header("bcc");
    parse_address_list(bcc);
    print_param_footer();
 
    print_param_header("messageid");
    parse_messageid(msgid);
    print_param_footer();
}
 
void parse_header(const mimetic::Header& header)
{
    parse_Rfc822_header(header);
 
    // Header class
    const mimetic::MimeVersion              &mimeVersion    = header.mimeVersion();
    const mimetic::ContentType              &contentType    = header.contentType();
    const mimetic::ContentTransferEncoding  &cte            = header.contentTransferEncoding();
    const mimetic::ContentDisposition       &cdispo         = header.contentDisposition();
    const mimetic::ContentDescription       &cdescr         = header.contentDescription();
    const mimetic::ContentId                &contentId      = header.contentId();
 
    print_param_header("Mime-Version");
    parse_mime_version(mimeVersion);
    print_param_footer();
 
    print_param_header("Content-Type");
    parse_content_type(contentType);
    print_param_footer();
 
    print_param_header("Content-Transfer-Encoding");
    parse_content_transfer_encoding(cte);
    print_param_footer();
 
    print_param_header("Content-Disposition");
    parse_content_disposition(cdispo);
    print_param_footer();
 
    print_param_header("Content-Description");
    parse_content_description(cdescr);
    print_param_footer();
 
    print_param_header("Content-Id");
    parse_content_id(contentId);
    print_param_footer();
}
 
void parse_body(const mimetic::Body& body);
void parse_mime_entity(const mimetic::MimeEntity& entity);
 
void parse_mime_entity(const mimetic::MimeEntity& entity)
{
    const mimetic::Header& header = entity.header();
    const mimetic::Body& body = entity.body();
 
    parse_header(header);
    parse_body(body);
}
 
void parse_body(const mimetic::Body& body)
{
    const std::string& preamble = body.preamble();
    const std::string& epilogue = body.epilogue();
    const mimetic::MimeEntityList& parts = body.parts();
 
    print_param_header("preamble");
    std::cout << preamble << std::endl;
    print_param_footer();
 
    print_param_header("epilogue");
    std::cout << epilogue << std::endl;
    print_param_footer();
 
    const mimetic::MimeEntity* owner       = body.owner();
    const mimetic::Header&     header      = owner->header();
    const mimetic::ContentType contentType = header.contentType();
 
    print_param_header("body (encoded)");
    std::cout << body << std::endl;
    print_param_footer();
 
    if (contentType.type() == "text") {
        const mimetic::ContentTransferEncoding& encoding = header.contentTransferEncoding();
        if (encoding.mechanism() == mimetic::ContentTransferEncoding::base64) {
            mimetic::Base64::Decoder decoder;
            std::string decoded;
            std::stringstream str;
            std::ostreambuf_iterator<char> oi(str);
            mimetic::decode(body.begin(), body.end(), decoder, oi);
 
            print_param_header("body (decoded)");
            decoded = str.str();
            std::cout << decoded << std::endl;
            print_param_footer();
        }
    }
 
    mimetic::MimeEntityList::const_iterator it;
    for(it = parts.begin(); it != parts.end(); ++it) {
        const mimetic::MimeEntity& entity = **it;
 
        parse_mime_entity(entity);
    }
}
 
 
void simple_parse(const std::string& content)
{
    mimetic::MimeEntity root_entity(content.begin(), content.end());
 
    parse_mime_entity(root_entity);
}
 
int main(int argc, char** argv)
{
    if (argc != 2) {
        std::cerr << "Please input a file." << std::endl;
        return EXIT_FAILURE;
    }
 
    std::string content;
    read(argv[1], content);
    //std::cout << content << std::endl;
 
    simple_parse(content);
 
    return EXIT_SUCCESS;
}