| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- #include "Message.h"
- #include "Image/JpegImageCollection.h"
- #include "Util/Base64.h"
- #include <Logging.h>
- #include <StringAlgorithm.h>
- #include <filesystem/path.h>
- #include <sstream>
- namespace MailServer {
- Message::Message(const std::string& address, const Util::Context& context, const std::string& message) :
- m_address(address),
- m_context(context),
- m_mimeBoundary("-_-InvalidBoundary-_-"),
- m_contentEncoding("none"),
- m_currentImage(0)
- {
- ProcessMessage(message);
- }
- std::string Decode(const std::string& data)
- {
- std::string result;
- if (StringAlgorithm::istarts_with(data, "=?utf-8?"))
- result = Util::Base64::Decode(std::string(data.begin() + 10, data.begin() + data.find_last_of('?')));
- else
- result = Util::Base64::Decode(data);
- return result;
- }
- void Message::ProcessMessage(const std::string& message)
- {
- try
- {
- Message::State::type state = Message::State::Header;
- std::string line;
- std::istringstream stream(message);
- while (std::getline(stream, line, '\r'))
- {
- StringAlgorithm::erase_all(line, '\n');
- switch (state)
- {
- case State::Header:
- state = ProcessHeaderLine(line);
- break;
- case State::Data:
- state = ProcessDataLine(line);
- break;
- case State::MimeBoundary:
- state = ProcessMimeBoundary(line);
- break;
- case State::Image:
- state = ProcessImage(line);
- break;
- }
- }
- if (StringAlgorithm::contains(m_contentEncoding, "base64"))
- {
- std::string decoded = Decode(m_subject);
- if (decoded.size() > 0)
- m_subject = decoded;
- }
- std::stringstream ss;
- ss << "From: " << m_sender << std::endl;
- Logging::Log(Logging::Severity::Debug, ss.str());
- ss.str("");
- ss << "To: " << m_receiver << std::endl;
- Logging::Log(Logging::Severity::Debug, ss.str());
- ss.str("");
- ss << "Subject: " << m_subject << std::endl;
- Logging::Log(Logging::Severity::Debug, ss.str());
- ss.str("");
- ss << "Received " << m_images.size() << " Images" << std::endl;
- Logging::Log(Logging::Severity::Info, ss.str());
- Image::JpegImageCollection imageCollection(m_images);
- filesystem::path path(m_context.path);
- path = path.make_absolute();
- path = path/filesystem::path(m_address);
- if (!path.exists())
- filesystem::create_directory(path);
- std::string fileName(Util::getTimeString());
- fileName.append(".jpg");
- path = path/filesystem::path(fileName);
- imageCollection.Save(path.str());
- ss.str("");
- ss << "Images Stored as " << path.str() << std::endl;
- Logging::Log(Logging::Severity::Info, ss.str());
- if (!m_context.url.empty())
- {
- std::stringstream url;
- url << m_context.url << "?ip=" << m_address << "&file=" << fileName;
- m_context.client.GetUrlContents(url.str());
- }
- }
- catch (std::exception& e)
- {
- std::stringstream ss;
- ss << "Message::ProcessMessage() - Error: " << e.what() << std::endl;
- Logging::Log(Logging::Severity::Error, ss.str());
- }
- }
- Message::State::type Message::ProcessHeaderLine(const std::string& line)
- {
- if (line.empty())
- return Message::State::Data;
- if (StringAlgorithm::istarts_with(line, "from:"))
- {
- m_sender = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
- return Message::State::Header;
- }
- if (StringAlgorithm::istarts_with(line, "to:"))
- {
- m_receiver = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
- return Message::State::Header;
- }
- if (StringAlgorithm::istarts_with(line, "subject:"))
- {
- m_subject = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
- return Message::State::Header;
- }
- if (StringAlgorithm::istarts_with(line, "date"))
- {
- m_date = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
- return Message::State::Header;
- }
- if (StringAlgorithm::istarts_with(line, "content-type:"))
- {
- m_contentType = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
- return Message::State::Header;
- }
- if (StringAlgorithm::istarts_with(line, "boundary") || StringAlgorithm::istarts_with(line, "\tboundary") || StringAlgorithm::istarts_with(line, " boundary"))
- {
- m_mimeBoundary = std::string("--").append(std::string(line.begin() + line.find_first_of('"') + 1, line.begin() + line.find_last_of('"')));
- return Message::State::Header;
- }
- if (StringAlgorithm::istarts_with(line, "content-transfer-encoding:"))
- {
- m_contentEncoding = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
- return Message::State::Header;
- }
- return Message::State::Header;
- }
- Message::State::type Message::ProcessDataLine(const std::string& line)
- {
- if (StringAlgorithm::istarts_with(line, m_mimeBoundary))
- {
- m_contentType = "";
- return Message::State::MimeBoundary;
- }
- return Message::State::Data;
- }
- Message::State::type Message::ProcessMimeBoundary(const std::string& line)
- {
- if (line.empty())
- {
- if (StringAlgorithm::istarts_with(m_contentType, "image/jpeg") || StringAlgorithm::istarts_with(m_contentType, "image/jpg"))
- {
- m_mimeImages.push_back(Image::MimeImage(m_imageName));
- m_imageName = "";
- return Message::State::Image;
- }
- return Message::State::Data;
- }
- if (StringAlgorithm::istarts_with(line, "content-type:"))
- {
- m_contentType = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
- return Message::State::MimeBoundary;
- }
- if (StringAlgorithm::istarts_with(line, "name") || StringAlgorithm::istarts_with(line, "\tname"))
- {
- m_imageName = "image.jpg";
- //m_imageName = Decode(std::string(line.begin() + line.find_first_of('"') + 1, line.begin() + line.find_last_of('"')));
- return Message::State::MimeBoundary;
- }
- if (StringAlgorithm::istarts_with(line, "content-transfer-encoding:"))
- {
- m_contentEncoding = std::string(line.begin() + line.find_first_of(' ') + 1, line.end());
- return Message::State::MimeBoundary;
- }
- return Message::State::MimeBoundary;
- }
- Message::State::type Message::ProcessImage(const std::string& line)
- {
- if (StringAlgorithm::istarts_with(line, m_mimeBoundary))
- {
- m_images.push_back(m_mimeImages[m_currentImage].DecodeImageData());
- ++m_currentImage;
- m_contentType = "";
- return Message::State::MimeBoundary;
- }
- m_mimeImages[m_currentImage].AppendData(line);
- return Message::State::Image;
- }
- } // namespace MailServer
|