- resultify send-out pipeline for better error reporting

- early ignore sending out smtp messages with no recipients
This commit is contained in:
holger krekel
2019-10-02 18:45:31 +02:00
parent 3f7995a7ea
commit 489cdd1b24
4 changed files with 70 additions and 54 deletions

View File

@@ -1245,8 +1245,11 @@ pub unsafe extern "C" fn dc_forward_msgs(
let ffi_context = &*context;
ffi_context
.with_inner(|ctx| chat::forward_msgs(ctx, ids, chat_id))
.unwrap_or_log_default(ctx, "Failed to forard message")
.with_inner(|ctx| {
chat::forward_msgs(ctx, ids, chat_id)
.unwrap_or_log_default(ctx, "Failed to forward message")
})
.unwrap_or_default()
}
#[no_mangle]

View File

@@ -805,8 +805,7 @@ pub fn send_msg(context: &Context, chat_id: u32, msg: &mut Message) -> Result<u3
break;
} else {
if let Ok(mut copy) = Message::load_from_db(context, id as u32) {
// TODO: handle cleanup and return early instead
send_msg(context, 0, &mut copy).unwrap();
send_msg(context, 0, &mut copy)?;
}
}
}
@@ -1421,7 +1420,7 @@ pub(crate) fn add_contact_to_chat_ex(
msg.param.set_int(Param::Cmd, 4);
msg.param.set(Param::Arg, contact.get_addr());
msg.param.set_int(Param::Arg2, from_handshake.into());
msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default();
msg.id = send_msg(context, chat_id, &mut msg)?;
context.call_cb(Event::MsgsChanged {
chat_id,
msg_id: msg.id,
@@ -1532,7 +1531,7 @@ pub fn remove_contact_from_chat(
}
msg.param.set_int(Param::Cmd, 5);
msg.param.set(Param::Arg, contact.get_addr());
msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default();
msg.id = send_msg(context, chat_id, &mut msg)?;
context.call_cb(Event::MsgsChanged {
chat_id,
msg_id: msg.id,
@@ -1629,7 +1628,7 @@ pub fn set_chat_name(
if !chat.name.is_empty() {
msg.param.set(Param::Arg, &chat.name);
}
msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default();
msg.id = send_msg(context, chat_id, &mut msg)?;
context.call_cb(Event::MsgsChanged {
chat_id,
msg_id: msg.id,
@@ -1698,7 +1697,7 @@ pub fn set_chat_profile_image(
"",
DC_CONTACT_ID_SELF,
));
msg.id = send_msg(context, chat_id, &mut msg).unwrap_or_default();
msg.id = send_msg(context, chat_id, &mut msg)?;
emit_event!(
context,
Event::MsgsChanged {

View File

@@ -167,32 +167,36 @@ impl Job {
// was sent we need to mark it in the database ASAP as we
// otherwise might send it twice.
let mut sock = context.smtp.lock().unwrap();
if !sock.send(context, recipients_list, body) {
sock.disconnect();
self.try_again_later(-1i32, sock.error.clone());
} else {
// smtp success, update DB as quick as possible
if 0 != self.foreign_id {
message::update_msg_state(
context,
self.foreign_id,
MessageState::OutDelivered,
);
let chat_id: i32 = context
.sql
.query_get_value(
context,
"SELECT chat_id FROM msgs WHERE id=?",
params![self.foreign_id as i32],
)
.unwrap_or_default();
context.call_cb(Event::MsgDelivered {
chat_id: chat_id as u32,
msg_id: self.foreign_id,
});
match sock.send(context, recipients_list, body) {
Err(err) => {
sock.disconnect();
warn!(context, "smtp failed: {}", err);
self.try_again_later(-1i32, Some(err.to_string()));
}
Ok(()) => {
// smtp success, update db ASAP, then delete smtp file
if 0 != self.foreign_id {
message::update_msg_state(
context,
self.foreign_id,
MessageState::OutDelivered,
);
let chat_id: i32 = context
.sql
.query_get_value(
context,
"SELECT chat_id FROM msgs WHERE id=?",
params![self.foreign_id as i32],
)
.unwrap_or_default();
context.call_cb(Event::MsgDelivered {
chat_id: chat_id as u32,
msg_id: self.foreign_id,
});
}
// now also delete the generated file
dc_delete_file(context, filename);
}
// now also delete the generated file
dc_delete_file(context, filename);
}
} else {
warn!(context, "Missing recipients for job {}", self.job_id,);
@@ -214,7 +218,7 @@ impl Job {
if !inbox.is_connected() {
connect_to_inbox(context, &inbox);
if !inbox.is_connected() {
self.try_again_later(3, None);
self.try_again_later(3, Some("could not connect".into()));
return;
}
}
@@ -612,10 +616,6 @@ pub fn job_action_exists(context: &Context, action: Action) -> bool {
pub fn job_send_msg(context: &Context, msg_id: u32) -> Result<(), Error> {
let mut mimefactory = MimeFactory::load_msg(context, msg_id)?;
ensure!(!mimefactory.recipients_addr.is_empty(),
"msg {} has no recipients, can not smtp-sent", msg_id
);
if chat::msgtype_has_file(mimefactory.msg.type_0) {
let file_param = mimefactory
.msg
@@ -672,6 +672,15 @@ pub fn job_send_msg(context: &Context, msg_id: u32) -> Result<(), Error> {
.recipients_addr
.push(mimefactory.from_addr.to_string());
}
if mimefactory.recipients_addr.is_empty() {
warn!(
context,
"message {} has no recipient, skipping smtp-send", msg_id
);
return Ok(());
}
if mimefactory.out_gossiped {
chat::set_gossiped_timestamp(context, mimefactory.msg.chat_id, time());
}

View File

@@ -3,6 +3,7 @@ use lettre::*;
use crate::constants::*;
use crate::context::Context;
use crate::error::Error;
use crate::events::Event;
use crate::login_param::LoginParam;
use crate::oauth2::*;
@@ -14,7 +15,6 @@ pub struct Smtp {
transport_connected: bool,
/// Email address we are sending from.
from: Option<EmailAddress>,
pub error: Option<String>,
}
impl Smtp {
@@ -24,7 +24,6 @@ impl Smtp {
transport: None,
transport_connected: false,
from: None,
error: None,
}
}
@@ -132,11 +131,19 @@ impl Smtp {
context: &Context,
recipients: Vec<EmailAddress>,
message: Vec<u8>,
) -> bool {
) -> Result<(), Error> {
let message_len = message.len();
let recipients_display = recipients
.iter()
.map(|x| format!("{}", x))
.collect::<Vec<String>>()
.join(",");
if let Some(ref mut transport) = self.transport {
let envelope = Envelope::new(self.from.clone(), recipients).expect("invalid envelope");
let envelope = Envelope::new(self.from.clone(), recipients);
ensure!(envelope.is_ok(), "internal smtp-message construction fail");
let envelope = envelope.unwrap();
let mail = SendableEmail::new(
envelope,
"mail-id".into(), // TODO: random id
@@ -145,24 +152,22 @@ impl Smtp {
match transport.send(mail) {
Ok(_) => {
context.call_cb(Event::SmtpMessageSent(
"Message was sent to SMTP server".into(),
));
context.call_cb(Event::SmtpMessageSent(format!(
"Message len={} was smtp-sent to {}",
message_len, recipients_display
)));
self.transport_connected = true;
true
return Ok(());
}
Err(err) => {
warn!(
context,
"SMTP failed message size {}, error: {}", message_len, err
);
self.error = Some(format!("{}", err));
false
bail!("SMTP failed len={}: error: {}", message_len, err);
}
}
} else {
warn!(context, "SMTP Failed to send message to {:?}", recipients);
false
bail!(
"uh? SMTP has no transport, failed to send to {:?}",
recipients_display
);
}
}
}