Skip to content

Commit 80a4c32

Browse files
committed
Refactor mimefactory to have separate To field and recipient list
1 parent b17619b commit 80a4c32

File tree

1 file changed

+78
-65
lines changed

1 file changed

+78
-65
lines changed

src/mimefactory.rs

+78-65
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,26 @@ pub struct MimeFactory {
6666

6767
selfstatus: String,
6868

69-
/// Vector of pairs of recipient name and address
70-
recipients: Vec<(String, String)>,
69+
/// Vector of actual recipient addresses.
70+
///
71+
/// This is the list of addresses the message should be sent to.
72+
/// It is not the same as the `To` header,
73+
/// because in case of "member removed" message
74+
/// removed member is in the recipient list,
75+
/// but not in the `To` header.
76+
/// In case of broadcast lists there are multiple recipients,
77+
/// but the `To` header has no members.
78+
///
79+
/// If `bcc_self` configuration is enabled,
80+
/// this list will be extended with own address later,
81+
/// but `MimeFactory` is not responsible for this.
82+
recipients: Vec<String>,
83+
84+
/// Vector of pairs of recipient name and address that goes into the `To` field.
85+
///
86+
/// The list of actual message recipient addresses may be different,
87+
/// e.g. if members are hidden for broadcast lists.
88+
to: Vec<(String, String)>,
7189

7290
/// Vector of pairs of past group member name and addresses.
7391
past_members: Vec<(String, String)>,
@@ -138,6 +156,7 @@ impl MimeFactory {
138156
pub async fn from_msg(context: &Context, msg: Message) -> Result<MimeFactory> {
139157
let chat = Chat::load_from_db(context, msg.chat_id).await?;
140158
let attach_profile_data = Self::should_attach_profile_data(&msg);
159+
let undisclosed_recipients = chat.typ == Chattype::Broadcast;
141160

142161
let from_addr = context.get_primary_self_addr().await?;
143162
let config_displayname = context
@@ -155,23 +174,32 @@ impl MimeFactory {
155174
(name, None)
156175
};
157176

158-
let mut recipients = Vec::with_capacity(5);
177+
let mut recipients = Vec::new();
178+
let mut to = Vec::new();
159179
let mut past_members = Vec::new();
160180
let mut member_timestamps = Vec::new();
161181
let mut recipient_ids = HashSet::new();
162182
let mut req_mdn = false;
163183

164184
if chat.is_self_talk() {
165185
if msg.param.get_cmd() == SystemMessage::AutocryptSetupMessage {
166-
recipients.push((from_displayname.to_string(), from_addr.to_string()));
186+
recipients.push(from_addr.to_string());
187+
to.push((from_displayname.to_string(), from_addr.to_string()));
167188
}
168189
} else if chat.is_mailing_list() {
169190
let list_post = chat
170191
.param
171192
.get(Param::ListPost)
172193
.context("Can't write to mailinglist without ListPost param")?;
173-
recipients.push(("".to_string(), list_post.to_string()));
194+
to.push(("".to_string(), list_post.to_string()));
195+
recipients.push(list_post.to_string());
174196
} else {
197+
let email_to_remove = if msg.param.get_cmd() == SystemMessage::MemberRemovedFromGroup {
198+
msg.param.get(Param::Arg)
199+
} else {
200+
None
201+
};
202+
175203
context
176204
.sql
177205
.query_map(
@@ -196,17 +224,37 @@ impl MimeFactory {
196224
false => "".to_string(),
197225
};
198226
if add_timestamp >= remove_timestamp {
199-
if !recipients_contain_addr(&recipients, &addr) {
200-
recipients.push((name, addr));
201-
member_timestamps.push(add_timestamp);
227+
if !recipients_contain_addr(&to, &addr) {
228+
recipients.push(addr.clone());
229+
if !undisclosed_recipients {
230+
if let Some(email_to_remove) = email_to_remove {
231+
if email_to_remove != addr {
232+
to.push((name, addr));
233+
member_timestamps.push(add_timestamp);
234+
}
235+
} else {
236+
to.push((name, addr));
237+
member_timestamps.push(add_timestamp);
238+
}
239+
}
202240
}
203241
recipient_ids.insert(id);
204242
} else {
205243
// Row is a tombstone,
206244
// member is not actually part of the group.
207245
if !recipients_contain_addr(&past_members, &addr) {
208-
past_members.push((name, addr));
209-
member_timestamps.push(remove_timestamp);
246+
if let Some(email_to_remove) = email_to_remove {
247+
if email_to_remove == addr {
248+
// This is a "member removed" message,
249+
// we need to notify removed member
250+
// that it was removed.
251+
recipients.push(addr.clone());
252+
}
253+
}
254+
if !undisclosed_recipients {
255+
past_members.push((name, addr));
256+
member_timestamps.push(remove_timestamp);
257+
}
210258
}
211259
}
212260
}
@@ -253,14 +301,15 @@ impl MimeFactory {
253301

254302
debug_assert!(
255303
member_timestamps.is_empty()
256-
|| recipients.len() + past_members.len() == member_timestamps.len()
304+
|| to.len() + past_members.len() == member_timestamps.len()
257305
);
258306
let factory = MimeFactory {
259307
from_addr,
260308
from_displayname,
261309
sender_displayname,
262310
selfstatus,
263311
recipients,
312+
to,
264313
past_members,
265314
member_timestamps,
266315
timestamp: msg.timestamp_sort,
@@ -290,7 +339,8 @@ impl MimeFactory {
290339
from_displayname: "".to_string(),
291340
sender_displayname: None,
292341
selfstatus: "".to_string(),
293-
recipients: vec![("".to_string(), contact.get_addr().to_string())],
342+
recipients: vec![contact.get_addr().to_string()],
343+
to: vec![("".to_string(), contact.get_addr().to_string())],
294344
past_members: vec![],
295345
member_timestamps: vec![],
296346
timestamp,
@@ -316,11 +366,7 @@ impl MimeFactory {
316366
let self_addr = context.get_primary_self_addr().await?;
317367

318368
let mut res = Vec::new();
319-
for (_, addr) in self
320-
.recipients
321-
.iter()
322-
.filter(|(_, addr)| addr != &self_addr)
323-
{
369+
for addr in self.recipients.iter().filter(|&addr| *addr != self_addr) {
324370
res.push((Peerstate::from_addr(context, addr).await?, addr.clone()));
325371
}
326372

@@ -508,10 +554,7 @@ impl MimeFactory {
508554
}
509555

510556
pub fn recipients(&self) -> Vec<String> {
511-
self.recipients
512-
.iter()
513-
.map(|(_, addr)| addr.clone())
514-
.collect()
557+
self.recipients.clone()
515558
}
516559

517560
/// Consumes a `MimeFactory` and renders it into a message which is then stored in
@@ -521,56 +564,26 @@ impl MimeFactory {
521564

522565
let from = new_address_with_name(&self.from_displayname, self.from_addr.clone());
523566

524-
let undisclosed_recipients = match &self.loaded {
525-
Loaded::Message { chat, .. } => chat.typ == Chattype::Broadcast,
526-
Loaded::Mdn { .. } => false,
527-
};
528-
529567
let mut to = Vec::new();
530-
let mut past_members = Vec::new(); // Contents of `Chat-Group-Past-Members` header.
531-
if !undisclosed_recipients {
532-
let email_to_remove = match &self.loaded {
533-
Loaded::Message { msg, .. } => {
534-
if msg.param.get_cmd() == SystemMessage::MemberRemovedFromGroup {
535-
msg.param.get(Param::Arg)
536-
} else {
537-
None
538-
}
539-
}
540-
Loaded::Mdn { .. } => None,
541-
};
542-
543-
for (name, addr) in &self.recipients {
544-
if let Some(email_to_remove) = email_to_remove {
545-
if email_to_remove == addr {
546-
if name.is_empty() {
547-
past_members.push(Address::new_mailbox(addr.clone()));
548-
} else {
549-
past_members.push(new_address_with_name(name, addr.clone()));
550-
}
551-
continue;
552-
}
553-
}
554-
555-
if name.is_empty() {
556-
to.push(Address::new_mailbox(addr.clone()));
557-
} else {
558-
to.push(new_address_with_name(name, addr.clone()));
559-
}
568+
for (name, addr) in &self.to {
569+
if name.is_empty() {
570+
to.push(Address::new_mailbox(addr.clone()));
571+
} else {
572+
to.push(new_address_with_name(name, addr.clone()));
560573
}
574+
}
561575

562-
for (name, addr) in &self.past_members {
563-
if name.is_empty() {
564-
past_members.push(Address::new_mailbox(addr.clone()));
565-
} else {
566-
past_members.push(new_address_with_name(name, addr.clone()));
567-
}
576+
let mut past_members = Vec::new(); // Contents of `Chat-Group-Past-Members` header.
577+
for (name, addr) in &self.past_members {
578+
if name.is_empty() {
579+
past_members.push(Address::new_mailbox(addr.clone()));
580+
} else {
581+
past_members.push(new_address_with_name(name, addr.clone()));
568582
}
569583
}
570584

571585
debug_assert!(
572-
undisclosed_recipients
573-
|| self.member_timestamps.is_empty()
586+
self.member_timestamps.is_empty()
574587
|| to.len() + past_members.len() == self.member_timestamps.len()
575588
);
576589
if to.is_empty() {
@@ -597,7 +610,7 @@ impl MimeFactory {
597610
);
598611
}
599612

600-
if !undisclosed_recipients && !self.member_timestamps.is_empty() {
613+
if !self.member_timestamps.is_empty() {
601614
headers.push(
602615
Header::new_with_value(
603616
"Chat-Group-Member-Timestamps".into(),

0 commit comments

Comments
 (0)