karastojko / mailio

mailio is a cross platform C++ library for MIME format and SMTP, POP3 and IMAP protocols. It is based on standard C++ 17 and Boost library.
Other
374 stars 98 forks source link

want to use mailio::message::parse to handle Boost.Beast-powered form file uploads #123

Closed movepointsolutions closed 1 year ago

movepointsolutions commented 1 year ago
    std::string content_type = request.base()[http::field::content_type];
    const auto multipart = "multipart/form-data"s;
    if (content_type == "application/x-www-form-urlencoded") {
        auto url="http://post.data/?" + request_body;
        urls::url_view uv(url);
        auto pv = uv.params();
        for (auto p : pv) {
            if (p.key == "nickname")
                nickname = p.value;
            else if (p.key == "text")
                text = p.value;
            else if (p.key == "file")
                file = p.value;
        }
    } else if (content_type.starts_with(multipart)) {
        std::string msg = "From: Movepoint <internal@movepoint.ru>\r\n";
        for (const auto &f : request.base()) {
            msg += f.name_string();
            msg += ": "s;
            msg += f.value();
            msg += "\r\n";
        }
        msg += "\r\n" + request_body;

        mailio::message message;
        message.line_policy(mailio::codec::line_len_policy_t::RECOMMENDED, mailio::codec::line_len_policy_t::NONE);
        message.parse(msg);
        const auto parts = message.parts();
        for (const auto &p : parts) {
            std::cerr << p.name() << std::endl;
            if (p.name() == "nickname")
                nickname = p.content();
            else if (p.name() == "text")
                text = p.content();
        }
    }

here I output MIME parts names, but they are empty, as mailio doesn't handle this particular formdata content-type and doesn't extract name= (and filename=) from there. I was too lazy to handle multipart/form-data and boost.beast lacks its support too, so I need to contribute to one of these 2 projects (beast and mailio)

movepointsolutions commented 1 year ago

Can it be done such a way it would work both for emails and http streams? Above example prints filename as a name for attached file, but part names set in content-disposition headers are lost :(

movepointsolutions commented 1 year ago

Here's how a typical file upload looks loike:

-----------------------------1182853161458354044109031061
Content-Disposition: form-data; name="nickname"

Anek
-----------------------------1182853161458354044109031061
Content-Disposition: form-data; name="text"

1
-----------------------------1182853161458354044109031061
Content-Disposition: form-data; name="file"; filename="1.txt"
Content-Type: text/plain

-----------------------------1182853161458354044109031061
Content-Disposition: form-data; name="submit"

Send
-----------------------------1182853161458354044109031061--
karastojko commented 1 year ago

As commented in the PR, there is no sense to mix the HTTP with email protocols.