|
|
|
|
@@ -61,6 +61,9 @@ pub fn dc_receive_imf(
|
|
|
|
|
ensure!(mime_parser.has_headers(), "No Headers Found");
|
|
|
|
|
|
|
|
|
|
// the function returns the number of created messages in the database
|
|
|
|
|
let mut incoming = true;
|
|
|
|
|
let mut incoming_origin = Origin::Unknown;
|
|
|
|
|
let mut to_id = 0u32;
|
|
|
|
|
let mut chat_id = 0;
|
|
|
|
|
let mut hidden = false;
|
|
|
|
|
|
|
|
|
|
@@ -71,6 +74,8 @@ pub fn dc_receive_imf(
|
|
|
|
|
let mut created_db_entries = Vec::new();
|
|
|
|
|
let mut create_event_to_send = Some(CreateEvent::MsgsChanged);
|
|
|
|
|
|
|
|
|
|
let mut to_ids = ContactIds::new();
|
|
|
|
|
|
|
|
|
|
// helper method to handle early exit and memory cleanup
|
|
|
|
|
let cleanup = |context: &Context,
|
|
|
|
|
create_event_to_send: &Option<CreateEvent>,
|
|
|
|
|
@@ -97,31 +102,48 @@ pub fn dc_receive_imf(
|
|
|
|
|
sent_timestamp = mailparse::dateparse(value).unwrap_or_default();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make sure, to_ids starts with the first To:-address (Cc: is added in the loop below pass)
|
|
|
|
|
if let Some(field) = mime_parser.get(HeaderDef::To) {
|
|
|
|
|
dc_add_or_lookup_contacts_by_address_list(
|
|
|
|
|
context,
|
|
|
|
|
&field,
|
|
|
|
|
if !incoming {
|
|
|
|
|
Origin::OutgoingTo
|
|
|
|
|
} else if incoming_origin.is_verified() {
|
|
|
|
|
Origin::IncomingTo
|
|
|
|
|
} else {
|
|
|
|
|
Origin::IncomingUnknownTo
|
|
|
|
|
},
|
|
|
|
|
&mut to_ids,
|
|
|
|
|
)?;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get From: (it can be an address list!) and check if it is known (for known From:'s we add
|
|
|
|
|
// the other To:/Cc: in the 3rd pass)
|
|
|
|
|
// or if From: is equal to SELF (in this case, it is any outgoing messages,
|
|
|
|
|
// we do not check Return-Path any more as this is unreliable, see issue #150)
|
|
|
|
|
let mut from_id = 0;
|
|
|
|
|
let mut from_id_blocked = false;
|
|
|
|
|
let mut incoming = true;
|
|
|
|
|
let mut incoming_origin = Origin::Unknown;
|
|
|
|
|
|
|
|
|
|
if let Some(field_from) = mime_parser.get(HeaderDef::From_) {
|
|
|
|
|
let from_ids = dc_add_or_lookup_contacts_by_address_list(
|
|
|
|
|
let mut from_ids = ContactIds::new();
|
|
|
|
|
dc_add_or_lookup_contacts_by_address_list(
|
|
|
|
|
context,
|
|
|
|
|
&field_from,
|
|
|
|
|
Origin::IncomingUnknownFrom,
|
|
|
|
|
&mut from_ids,
|
|
|
|
|
)?;
|
|
|
|
|
if from_ids.len() > 1 {
|
|
|
|
|
warn!(
|
|
|
|
|
context,
|
|
|
|
|
"mail has more than one From address, only using first: {:?}", field_from
|
|
|
|
|
"mail has more than one address in From: {:?}", field_from
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
if from_ids.contains(&DC_CONTACT_ID_SELF) {
|
|
|
|
|
incoming = false;
|
|
|
|
|
from_id = DC_CONTACT_ID_SELF;
|
|
|
|
|
incoming_origin = Origin::OutgoingBcc;
|
|
|
|
|
if to_ids.len() == 1 && to_ids.contains(&DC_CONTACT_ID_SELF) {
|
|
|
|
|
from_id = DC_CONTACT_ID_SELF;
|
|
|
|
|
}
|
|
|
|
|
} else if !from_ids.is_empty() {
|
|
|
|
|
from_id = from_ids.get_index(0).cloned().unwrap_or_default();
|
|
|
|
|
incoming_origin = Contact::get_origin_by_id(context, from_id, &mut from_id_blocked)
|
|
|
|
|
@@ -133,23 +155,6 @@ pub fn dc_receive_imf(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut to_ids = ContactIds::new();
|
|
|
|
|
for header_def in &[HeaderDef::To, HeaderDef::Cc] {
|
|
|
|
|
if let Some(field) = mime_parser.get(header_def.clone()) {
|
|
|
|
|
to_ids.extend(&dc_add_or_lookup_contacts_by_address_list(
|
|
|
|
|
context,
|
|
|
|
|
&field,
|
|
|
|
|
if !incoming {
|
|
|
|
|
Origin::OutgoingTo
|
|
|
|
|
} else if incoming_origin.is_known() {
|
|
|
|
|
Origin::IncomingTo
|
|
|
|
|
} else {
|
|
|
|
|
Origin::IncomingUnknownTo
|
|
|
|
|
},
|
|
|
|
|
)?);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add parts
|
|
|
|
|
|
|
|
|
|
let rfc724_mid = match mime_parser.get_rfc724_mid() {
|
|
|
|
|
@@ -172,16 +177,17 @@ pub fn dc_receive_imf(
|
|
|
|
|
&mut mime_parser,
|
|
|
|
|
imf_raw,
|
|
|
|
|
incoming,
|
|
|
|
|
incoming_origin,
|
|
|
|
|
&mut incoming_origin,
|
|
|
|
|
server_folder.as_ref(),
|
|
|
|
|
server_uid,
|
|
|
|
|
&to_ids,
|
|
|
|
|
&mut to_ids,
|
|
|
|
|
&rfc724_mid,
|
|
|
|
|
&mut sent_timestamp,
|
|
|
|
|
from_id,
|
|
|
|
|
&mut from_id,
|
|
|
|
|
from_id_blocked,
|
|
|
|
|
&mut hidden,
|
|
|
|
|
&mut chat_id,
|
|
|
|
|
&mut to_id,
|
|
|
|
|
flags,
|
|
|
|
|
&mut needs_delete_job,
|
|
|
|
|
&mut insert_msg_id,
|
|
|
|
|
@@ -251,16 +257,17 @@ fn add_parts(
|
|
|
|
|
mut mime_parser: &mut MimeParser,
|
|
|
|
|
imf_raw: &[u8],
|
|
|
|
|
incoming: bool,
|
|
|
|
|
incoming_origin: Origin,
|
|
|
|
|
incoming_origin: &mut Origin,
|
|
|
|
|
server_folder: impl AsRef<str>,
|
|
|
|
|
server_uid: u32,
|
|
|
|
|
to_ids: &ContactIds,
|
|
|
|
|
to_ids: &mut ContactIds,
|
|
|
|
|
rfc724_mid: &str,
|
|
|
|
|
sent_timestamp: &mut i64,
|
|
|
|
|
from_id: u32,
|
|
|
|
|
from_id: &mut u32,
|
|
|
|
|
from_id_blocked: bool,
|
|
|
|
|
hidden: &mut bool,
|
|
|
|
|
chat_id: &mut u32,
|
|
|
|
|
to_id: &mut u32,
|
|
|
|
|
flags: u32,
|
|
|
|
|
needs_delete_job: &mut bool,
|
|
|
|
|
insert_msg_id: &mut MsgId,
|
|
|
|
|
@@ -274,7 +281,24 @@ fn add_parts(
|
|
|
|
|
let mut rcvd_timestamp = 0;
|
|
|
|
|
let mut mime_in_reply_to = String::new();
|
|
|
|
|
let mut mime_references = String::new();
|
|
|
|
|
let mut incoming_origin = incoming_origin;
|
|
|
|
|
|
|
|
|
|
// collect the rest information, CC: is added to the to-list, BCC: is ignored
|
|
|
|
|
// (we should not add BCC to groups as this would split groups. We could add them as "known contacts",
|
|
|
|
|
// however, the benefit is very small and this may leak data that is expected to be hidden)
|
|
|
|
|
if let Some(fld_cc) = mime_parser.get(HeaderDef::Cc) {
|
|
|
|
|
dc_add_or_lookup_contacts_by_address_list(
|
|
|
|
|
context,
|
|
|
|
|
fld_cc,
|
|
|
|
|
if !incoming {
|
|
|
|
|
Origin::OutgoingCc
|
|
|
|
|
} else if incoming_origin.is_verified() {
|
|
|
|
|
Origin::IncomingCc
|
|
|
|
|
} else {
|
|
|
|
|
Origin::IncomingUnknownCc
|
|
|
|
|
},
|
|
|
|
|
to_ids,
|
|
|
|
|
)?;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check, if the mail is already in our database - if so, just update the folder/uid
|
|
|
|
|
// (if the mail was moved around) and finish. (we may get a mail twice eg. if it is
|
|
|
|
|
@@ -314,15 +338,13 @@ fn add_parts(
|
|
|
|
|
// - outgoing messages introduce a chat with the first to: address if they are sent by a messenger
|
|
|
|
|
// - incoming messages introduce a chat only for known contacts if they are sent by a messenger
|
|
|
|
|
// (of course, the user can add other chats manually later)
|
|
|
|
|
let to_id: u32;
|
|
|
|
|
|
|
|
|
|
if incoming {
|
|
|
|
|
state = if 0 != flags & DC_IMAP_SEEN {
|
|
|
|
|
MessageState::InSeen
|
|
|
|
|
} else {
|
|
|
|
|
MessageState::InFresh
|
|
|
|
|
};
|
|
|
|
|
to_id = DC_CONTACT_ID_SELF;
|
|
|
|
|
*to_id = DC_CONTACT_ID_SELF;
|
|
|
|
|
let mut needs_stop_ongoing_process = false;
|
|
|
|
|
|
|
|
|
|
// handshake messages must be processed _before_ chats are created
|
|
|
|
|
@@ -332,7 +354,7 @@ fn add_parts(
|
|
|
|
|
msgrmsg = 1;
|
|
|
|
|
*chat_id = 0;
|
|
|
|
|
allow_creation = true;
|
|
|
|
|
match handle_securejoin_handshake(context, mime_parser, from_id) {
|
|
|
|
|
match handle_securejoin_handshake(context, mime_parser, *from_id) {
|
|
|
|
|
Ok(ret) => {
|
|
|
|
|
if ret.hide_this_msg {
|
|
|
|
|
*hidden = true;
|
|
|
|
|
@@ -354,7 +376,7 @@ fn add_parts(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let (test_normal_chat_id, test_normal_chat_id_blocked) =
|
|
|
|
|
chat::lookup_by_contact_id(context, from_id).unwrap_or_default();
|
|
|
|
|
chat::lookup_by_contact_id(context, *from_id).unwrap_or_default();
|
|
|
|
|
|
|
|
|
|
// get the chat_id - a chat_id here is no indicator that the chat is displayed in the normal list,
|
|
|
|
|
// it might also be blocked and displayed in the deaddrop as a result
|
|
|
|
|
@@ -374,7 +396,7 @@ fn add_parts(
|
|
|
|
|
&mut mime_parser,
|
|
|
|
|
allow_creation,
|
|
|
|
|
create_blocked,
|
|
|
|
|
from_id,
|
|
|
|
|
*from_id,
|
|
|
|
|
to_ids,
|
|
|
|
|
)?;
|
|
|
|
|
*chat_id = new_chat_id;
|
|
|
|
|
@@ -395,7 +417,7 @@ fn add_parts(
|
|
|
|
|
|
|
|
|
|
if *chat_id == 0 {
|
|
|
|
|
// try to create a normal chat
|
|
|
|
|
let create_blocked = if from_id == to_id {
|
|
|
|
|
let create_blocked = if *from_id == *to_id {
|
|
|
|
|
Blocked::Not
|
|
|
|
|
} else {
|
|
|
|
|
Blocked::Deaddrop
|
|
|
|
|
@@ -406,7 +428,7 @@ fn add_parts(
|
|
|
|
|
chat_id_blocked = test_normal_chat_id_blocked;
|
|
|
|
|
} else if allow_creation {
|
|
|
|
|
let (id, bl) =
|
|
|
|
|
chat::create_or_lookup_by_contact_id(context, from_id, create_blocked)
|
|
|
|
|
chat::create_or_lookup_by_contact_id(context, *from_id, create_blocked)
|
|
|
|
|
.unwrap_or_default();
|
|
|
|
|
*chat_id = id;
|
|
|
|
|
chat_id_blocked = bl;
|
|
|
|
|
@@ -418,13 +440,13 @@ fn add_parts(
|
|
|
|
|
} else if is_reply_to_known_message(context, mime_parser) {
|
|
|
|
|
// we do not want any chat to be created implicitly. Because of the origin-scale-up,
|
|
|
|
|
// the contact requests will pop up and this should be just fine.
|
|
|
|
|
Contact::scaleup_origin_by_id(context, from_id, Origin::IncomingReplyTo);
|
|
|
|
|
Contact::scaleup_origin_by_id(context, *from_id, Origin::IncomingReplyTo);
|
|
|
|
|
info!(
|
|
|
|
|
context,
|
|
|
|
|
"Message is a reply to a known message, mark sender as known.",
|
|
|
|
|
);
|
|
|
|
|
if !incoming_origin.is_known() {
|
|
|
|
|
incoming_origin = Origin::IncomingReplyTo;
|
|
|
|
|
if !incoming_origin.is_verified() {
|
|
|
|
|
*incoming_origin = Origin::IncomingReplyTo;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -439,7 +461,7 @@ fn add_parts(
|
|
|
|
|
// to not result in a chatlist-contact-request (this would require the state FRESH)
|
|
|
|
|
if Blocked::Not != chat_id_blocked
|
|
|
|
|
&& state == MessageState::InFresh
|
|
|
|
|
&& !incoming_origin.is_known()
|
|
|
|
|
&& !incoming_origin.is_verified()
|
|
|
|
|
&& msgrmsg == 0
|
|
|
|
|
&& show_emails != ShowEmails::All
|
|
|
|
|
{
|
|
|
|
|
@@ -458,15 +480,16 @@ fn add_parts(
|
|
|
|
|
// the mail is on the IMAP server, probably it is also delivered.
|
|
|
|
|
// We cannot recreate other states (read, error).
|
|
|
|
|
state = MessageState::OutDelivered;
|
|
|
|
|
to_id = to_ids.get_index(0).cloned().unwrap_or_default();
|
|
|
|
|
*from_id = DC_CONTACT_ID_SELF;
|
|
|
|
|
if !to_ids.is_empty() {
|
|
|
|
|
*to_id = to_ids.get_index(0).cloned().unwrap_or_default();
|
|
|
|
|
if *chat_id == 0 {
|
|
|
|
|
let (new_chat_id, new_chat_id_blocked) = create_or_lookup_group(
|
|
|
|
|
context,
|
|
|
|
|
&mut mime_parser,
|
|
|
|
|
allow_creation,
|
|
|
|
|
Blocked::Not,
|
|
|
|
|
from_id,
|
|
|
|
|
*from_id,
|
|
|
|
|
to_ids,
|
|
|
|
|
)?;
|
|
|
|
|
*chat_id = new_chat_id;
|
|
|
|
|
@@ -478,13 +501,14 @@ fn add_parts(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if *chat_id == 0 && allow_creation {
|
|
|
|
|
let create_blocked = if 0 != msgrmsg && !Contact::is_blocked_load(context, to_id) {
|
|
|
|
|
let create_blocked = if 0 != msgrmsg && !Contact::is_blocked_load(context, *to_id) {
|
|
|
|
|
Blocked::Not
|
|
|
|
|
} else {
|
|
|
|
|
Blocked::Deaddrop
|
|
|
|
|
};
|
|
|
|
|
let (id, bl) = chat::create_or_lookup_by_contact_id(context, to_id, create_blocked)
|
|
|
|
|
.unwrap_or_default();
|
|
|
|
|
let (id, bl) =
|
|
|
|
|
chat::create_or_lookup_by_contact_id(context, *to_id, create_blocked)
|
|
|
|
|
.unwrap_or_default();
|
|
|
|
|
*chat_id = id;
|
|
|
|
|
chat_id_blocked = bl;
|
|
|
|
|
|
|
|
|
|
@@ -497,7 +521,7 @@ fn add_parts(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
let self_sent = from_id == DC_CONTACT_ID_SELF
|
|
|
|
|
let self_sent = *from_id == DC_CONTACT_ID_SELF
|
|
|
|
|
&& to_ids.len() == 1
|
|
|
|
|
&& to_ids.contains(&DC_CONTACT_ID_SELF);
|
|
|
|
|
|
|
|
|
|
@@ -524,7 +548,7 @@ fn add_parts(
|
|
|
|
|
calc_timestamps(
|
|
|
|
|
context,
|
|
|
|
|
*chat_id,
|
|
|
|
|
from_id,
|
|
|
|
|
*from_id,
|
|
|
|
|
*sent_timestamp,
|
|
|
|
|
0 == flags & DC_IMAP_SEEN,
|
|
|
|
|
&mut sort_timestamp,
|
|
|
|
|
@@ -588,8 +612,8 @@ fn add_parts(
|
|
|
|
|
server_folder.as_ref(),
|
|
|
|
|
server_uid as i32,
|
|
|
|
|
*chat_id as i32,
|
|
|
|
|
from_id as i32,
|
|
|
|
|
to_id as i32,
|
|
|
|
|
*from_id as i32,
|
|
|
|
|
*to_id as i32,
|
|
|
|
|
sort_timestamp,
|
|
|
|
|
*sent_timestamp,
|
|
|
|
|
rcvd_timestamp,
|
|
|
|
|
@@ -1513,7 +1537,8 @@ fn dc_add_or_lookup_contacts_by_address_list(
|
|
|
|
|
context: &Context,
|
|
|
|
|
addr_list_raw: &str,
|
|
|
|
|
origin: Origin,
|
|
|
|
|
) -> Result<ContactIds> {
|
|
|
|
|
to_ids: &mut ContactIds,
|
|
|
|
|
) -> Result<()> {
|
|
|
|
|
let addrs = match mailparse::addrparse(addr_list_raw) {
|
|
|
|
|
Ok(addrs) => addrs,
|
|
|
|
|
Err(err) => {
|
|
|
|
|
@@ -1521,11 +1546,10 @@ fn dc_add_or_lookup_contacts_by_address_list(
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let mut contact_ids = ContactIds::new();
|
|
|
|
|
for addr in addrs.iter() {
|
|
|
|
|
match addr {
|
|
|
|
|
mailparse::MailAddr::Single(info) => {
|
|
|
|
|
contact_ids.insert(add_or_lookup_contact_by_addr(
|
|
|
|
|
to_ids.insert(add_or_lookup_contact_by_addr(
|
|
|
|
|
context,
|
|
|
|
|
&info.display_name,
|
|
|
|
|
&info.addr,
|
|
|
|
|
@@ -1534,7 +1558,7 @@ fn dc_add_or_lookup_contacts_by_address_list(
|
|
|
|
|
}
|
|
|
|
|
mailparse::MailAddr::Group(infos) => {
|
|
|
|
|
for info in &infos.addrs {
|
|
|
|
|
contact_ids.insert(add_or_lookup_contact_by_addr(
|
|
|
|
|
to_ids.insert(add_or_lookup_contact_by_addr(
|
|
|
|
|
context,
|
|
|
|
|
&info.display_name,
|
|
|
|
|
&info.addr,
|
|
|
|
|
@@ -1545,7 +1569,7 @@ fn dc_add_or_lookup_contacts_by_address_list(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(contact_ids)
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Add contacts to database on receiving messages.
|
|
|
|
|
|