Files
2020-06-14 16:37:45 +02:00

221 lines
6.1 KiB
C++

#include "Message.h"
#include "Util/Base64.h"
#include <JpegImageCollection.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;
Http::HttpRequest request(url.str());
m_context.client.Open(request);
}
}
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