|
|
|
@ -11,6 +11,8 @@
|
|
|
|
|
#include <sstream>
|
|
|
|
|
#include <list> //what for?
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <typeinfo>
|
|
|
|
|
|
|
|
|
|
// sleep():
|
|
|
|
|
#ifdef WIN32
|
|
|
|
|
#include <windows.h>
|
|
|
|
@ -70,8 +72,14 @@ namespace pEp {
|
|
|
|
|
|
|
|
|
|
void pEpTransportMail::print_stats(std::string inbox)
|
|
|
|
|
{
|
|
|
|
|
mailio::imap::mailbox_stat_t inbox_stat = conn_imap->select(inbox);
|
|
|
|
|
print_stats(inbox_stat);
|
|
|
|
|
try {
|
|
|
|
|
mailio::imap::mailbox_stat_t inbox_stat = conn_imap->statistics(inbox);
|
|
|
|
|
print_stats(inbox_stat);
|
|
|
|
|
} catch (mailio::dialog_error e) {
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
} catch (std::runtime_error e) {
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pEpTransportMail::startup()
|
|
|
|
@ -102,6 +110,11 @@ namespace pEp {
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
throw(TransportError(PEP_tsc_recv_config_incomplete_or_wrong));
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
conn_imap->select("inbox");
|
|
|
|
|
} catch (mailio::imap_error e) {
|
|
|
|
|
throw(TransportError(PEP_tsc_unknown_imap_error));
|
|
|
|
|
}
|
|
|
|
|
if (!protocol_thread.joinable()) {
|
|
|
|
|
protocol_thread_stop.store(false);
|
|
|
|
|
protocol_thread = std::thread(&pEpTransportMail::worker, this);
|
|
|
|
@ -157,9 +170,14 @@ namespace pEp {
|
|
|
|
|
// e.what() might be:
|
|
|
|
|
// Server connecting failed
|
|
|
|
|
// Server connecting timed out
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
throw(TransportError(PEP_tsc_cannot_reach_smtp_server));
|
|
|
|
|
} catch (mailio::smtp_error e) {
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
throw(TransportError(PEP_tsc_send_config_incomplete_or_wrong));
|
|
|
|
|
} catch (std::exception e) {
|
|
|
|
|
pEpLogClass("Now this is weird. Why did we end up here?");
|
|
|
|
|
pEpLogClass(std::string(typeid(e).name()) + ": " + std::string(e.what()));
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
conn->authenticate(login_smtp.username, login_smtp.passphrase, login_smtp.auth_method);
|
|
|
|
@ -171,13 +189,14 @@ namespace pEp {
|
|
|
|
|
// Username rejection
|
|
|
|
|
// Password rejection
|
|
|
|
|
// Parsing server failure
|
|
|
|
|
pep_tsc = PEP_tsc_cannot_reach_smtp_server;
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
pep_tsc = PEP_tsc_send_config_incomplete_or_wrong;
|
|
|
|
|
throw(TransportError(pep_tsc));
|
|
|
|
|
// Other possible values:
|
|
|
|
|
// PEP_tsc_network_timeout = 0x0080000a,
|
|
|
|
|
// PEP_tsc_unknown_smtp_error = 0x01801fff,
|
|
|
|
|
// PEP_tsc_no_send_config
|
|
|
|
|
// PEP_tsc_send_config_incomplete_or_wrong
|
|
|
|
|
// PEP_tsc_cannot_reach_smtp_server
|
|
|
|
|
} catch (mailio::dialog_error e) {
|
|
|
|
|
// e.what() might be:
|
|
|
|
|
// Network sending error
|
|
|
|
@ -186,6 +205,12 @@ namespace pEp {
|
|
|
|
|
// Network receiving error
|
|
|
|
|
// Network receiving failed
|
|
|
|
|
// Network receiving timed out
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
pep_tsc = PEP_tsc_cannot_reach_smtp_server;
|
|
|
|
|
throw(TransportError(pep_tsc));
|
|
|
|
|
} catch (std::exception e) {
|
|
|
|
|
pEpLogClass("Now this is weird. Why did we end up here?");
|
|
|
|
|
pEpLogClass(std::string(typeid(e).name()) + ": " + std::string(e.what()));
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
std::string answer = conn->submit(mmsg); // TODO: log the result
|
|
|
|
@ -219,13 +244,15 @@ namespace pEp {
|
|
|
|
|
// Network receiving error
|
|
|
|
|
// Network receiving failed
|
|
|
|
|
// Network receiving timed out
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
pep_tsc = PEP_tsc_unknown_smtp_error;
|
|
|
|
|
}
|
|
|
|
|
// if nothing failed, pep_tsc is still PEP_tsc_message_on_the_way
|
|
|
|
|
cb_sendto_result(get_id(), msg->id, pep_tsc);
|
|
|
|
|
try {
|
|
|
|
|
//conn_imap->append("Sent", mmsg);
|
|
|
|
|
// This usually fails in the test, I don't know why.
|
|
|
|
|
// And I'm not even sure if it's a) needed or b) even asked for?
|
|
|
|
|
conn_imap->append("Sent", mmsg);
|
|
|
|
|
// Should I even do that?
|
|
|
|
|
// I guess it can be deleted anytime, so idk really.
|
|
|
|
|
} catch (mailio::imap_error e) {
|
|
|
|
|
// e.what() might be:
|
|
|
|
|
// Message appending failure
|
|
|
|
@ -239,15 +266,19 @@ namespace pEp {
|
|
|
|
|
// Network receiving error
|
|
|
|
|
// Network receiving failed
|
|
|
|
|
// Network receiving timed out
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
} catch (mailio::message_error e) {
|
|
|
|
|
// e.what() might be:
|
|
|
|
|
// No boundary for multipart message.
|
|
|
|
|
// No author.
|
|
|
|
|
// No sender for multiple authors.
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
} catch (mailio::mime_error e) {
|
|
|
|
|
// e.what() might be:
|
|
|
|
|
// Formatting failure, non multipart message with boundary.
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
}
|
|
|
|
|
pEpLogClass("returning");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
::message *pEpTransportMail::recvnext()
|
|
|
|
@ -274,16 +305,6 @@ namespace pEp {
|
|
|
|
|
// PEP_tsc_unknown_imap_error = 0x01802fff,
|
|
|
|
|
try {
|
|
|
|
|
conn_imap->fetch("inbox", message_id, mmsg, false);
|
|
|
|
|
} catch (mailio::imap_error e) {
|
|
|
|
|
// e.what() could be:
|
|
|
|
|
// Fetching message failure.
|
|
|
|
|
// Parsing failure
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
throw(TransportError(PEP_tsc_unknown_imap_error));
|
|
|
|
|
} catch (mailio::message_error) {
|
|
|
|
|
// message_error No author address
|
|
|
|
|
} catch (mailio::mime_error) {
|
|
|
|
|
// lots of mime_error's
|
|
|
|
|
} catch (mailio::dialog_error e) {
|
|
|
|
|
// e.what() might be:
|
|
|
|
|
// Network sending error
|
|
|
|
@ -292,10 +313,27 @@ namespace pEp {
|
|
|
|
|
// Network receiving error
|
|
|
|
|
// Network receiving failed
|
|
|
|
|
// Network receiving timed out
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
throw(TransportError(PEP_tsc_cannot_reach_imap_server));
|
|
|
|
|
} catch (mailio::imap_error e) {
|
|
|
|
|
// e.what() could be:
|
|
|
|
|
// Fetching message failure.
|
|
|
|
|
// Parsing failure
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
throw(TransportError(PEP_tsc_unknown_imap_error));
|
|
|
|
|
} catch (mailio::message_error e) {
|
|
|
|
|
// message_error No author address
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
throw(TransportError(PEP_tsc_unknown_imap_error));
|
|
|
|
|
} catch (mailio::mime_error e) {
|
|
|
|
|
// lots of mime_error's
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
throw(TransportError(PEP_tsc_unknown_imap_error));
|
|
|
|
|
} catch (std::logic_error e) {
|
|
|
|
|
// e might be of class:
|
|
|
|
|
// std::invalid_argument
|
|
|
|
|
// std::out_of_rangev
|
|
|
|
|
// std::out_of_range
|
|
|
|
|
pEpLogClass("logic error " + std::string(e.what()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Convert the mailio message struct into a pEp message struct using our conversion operator.
|
|
|
|
@ -389,25 +427,48 @@ namespace pEp {
|
|
|
|
|
// private
|
|
|
|
|
void pEpTransportMail::worker()
|
|
|
|
|
{
|
|
|
|
|
mailio::imap::mailbox_stat_t inbox_stat;
|
|
|
|
|
static unsigned int last_pushed;
|
|
|
|
|
bool previous_error = false;
|
|
|
|
|
std::list<mailio::imap::search_condition_t> search_condition;
|
|
|
|
|
search_condition.push_back(
|
|
|
|
|
mailio::imaps::search_condition_t(mailio::imaps::search_condition_t::UNSEEN));
|
|
|
|
|
while (!protocol_thread_stop.load()) {
|
|
|
|
|
// conn_imap->search( welp, mailio atm doesn't support to search for unread messages
|
|
|
|
|
// only… we could try something like:
|
|
|
|
|
do {
|
|
|
|
|
inbox_stat = conn_imap->select("inbox");
|
|
|
|
|
print_stats(inbox_stat);
|
|
|
|
|
if (inbox_stat.messages_first_unseen) {
|
|
|
|
|
rx_queue.push(inbox_stat.messages_first_unseen);
|
|
|
|
|
cb_incomming_message(get_id(), PEP_tsc_ready);
|
|
|
|
|
}
|
|
|
|
|
// but that only gives us one unread email.
|
|
|
|
|
// I guess we poll this for now and wait for search-for-unseen (should be in
|
|
|
|
|
// mailio soon-ish) or IMAP IDLE (planned, but no ETA known)
|
|
|
|
|
} while (inbox_stat.messages_first_unseen);
|
|
|
|
|
// No, it's implemented in a feature branch, release ETA february. I'll make use of
|
|
|
|
|
// it now already, fuck it.
|
|
|
|
|
//
|
|
|
|
|
// or should we abandon mailio and use vmime or mailcore2?
|
|
|
|
|
// It would be neat to trigger this from the application/adapter, so we don't
|
|
|
|
|
// have to poll it repeatedly There ought to be a callback to do this?
|
|
|
|
|
sleep(10);
|
|
|
|
|
// have to poll it repeatedly.
|
|
|
|
|
//
|
|
|
|
|
// There ought to be a callback to do this?
|
|
|
|
|
std::list<unsigned long> unseen_msg_numbers;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
conn_imap->search(search_condition, unseen_msg_numbers);
|
|
|
|
|
} catch (mailio::imap_error e) {
|
|
|
|
|
pEpLogClass(e.what());
|
|
|
|
|
if (previous_error)
|
|
|
|
|
throw(TransportError(PEP_tsc_connection_down)); // or PEP_tsc_unknown_imap_error
|
|
|
|
|
// previous_error = true;
|
|
|
|
|
sleep(10);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
for (int msg_no = unseen_msg_numbers.front(); !unseen_msg_numbers.empty();
|
|
|
|
|
unseen_msg_numbers.pop_front()) {
|
|
|
|
|
if (msg_no <= last_pushed) {
|
|
|
|
|
pEpLogClass(
|
|
|
|
|
"Message no " + std::to_string(msg_no) +
|
|
|
|
|
" already pushed to rx_queue before");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
rx_queue.push(msg_no);
|
|
|
|
|
last_pushed = msg_no;
|
|
|
|
|
pEpLogClass("Message no " + std::to_string(msg_no) + " pushed to rx_queue");
|
|
|
|
|
cb_incomming_message(get_id(), PEP_tsc_ready);
|
|
|
|
|
}
|
|
|
|
|
sleep(10); // we will get rid of this thing as soon as IMAP IDLE is implemented in mailio.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|