Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions python/src/deltachat/chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,29 @@ def send_msg(self, msg: Message) -> Message:
msg._dc_msg = sent_msg._dc_msg
return msg

def send_msg_sync(self, msg: Message) -> Message:
"""Send a message synchronously.
This bypasses the IO scheduler and creates its own SMTP connection.

:param msg: a :class:`deltachat.message.Message` instance
previously returned by
e.g. :meth:`deltachat.message.Message.new_empty`.
:raises ValueError: if message can not be sent.

:returns: a :class:`deltachat.message.Message` instance as
sent out. This is the same object as was passed in, which
has been modified with the new state of the core.
"""
sent_id = lib.dc_send_msg_sync(self.account._dc_context, self.id, msg._dc_msg)
if sent_id == 0:
raise ValueError("message could not be sent")
# modify message in place to avoid bad state for the caller

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is copy-pasted from a function above.

sent_msg = Message.from_db(self.account, sent_id)
if sent_msg is None:
raise ValueError("cannot load just sent message from the database")
msg._dc_msg = sent_msg._dc_msg
return msg

def send_text(self, text):
"""send a text message and return the resulting Message instance.

Expand Down
25 changes: 25 additions & 0 deletions python/tests/test_1_online.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,31 @@ def test_forward_own_message(acfactory, lp):
assert msg_in.is_forwarded()


def test_send_msg_sync(acfactory, lp):
ac1, ac2 = acfactory.get_online_accounts(2)
chat1 = acfactory.get_accepted_chat(ac1, ac2)

# Send some message from ac1
# so we are testing not the first message
# being sent synchronously.
lp.sec("ac1: send message to ac2")
chat1.send_text("message")

lp.sec("ac2: receive message")
msg_in = ac2._evtracker.wait_next_incoming_message()
assert msg_in.text == "message"

# Stop I/O and send message synchronously.
ac1.stop_io()
msg1 = Message.new_empty(ac1, "text")
msg1.set_text("message1")
chat1.send_msg_sync(msg1)

lp.sec("ac2: receive message")
msg_in = ac2._evtracker.wait_next_incoming_message()

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test gets stuck without the fix, likely here because the message is never sent out as it tries to send rowid 1 from smtp table.

assert msg_in.text == "message1"


def test_resend_message(acfactory, lp):
ac1, ac2 = acfactory.get_online_accounts(2)
chat1 = acfactory.get_accepted_chat(ac1, ac2)
Expand Down
8 changes: 4 additions & 4 deletions src/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3037,21 +3037,21 @@ WHERE id=?
)?;
let all_recipients = recipients.join(" ");
if let Some(pre_msg) = &rendered_pre_msg {
let row_id = stmt.execute((
let row_id = stmt.insert((
&pre_msg.rfc724_mid,
&all_recipients,
&pre_msg.message,
msg.id,
))?;
row_ids.push(row_id.try_into()?);
row_ids.push(row_id);
}
let row_id = stmt.execute((
let row_id = stmt.insert((
&rendered_msg.rfc724_mid,
&all_recipients,
&rendered_msg.message,
msg.id,
))?;
row_ids.push(row_id.try_into()?);
row_ids.push(row_id);
}
Ok(row_ids)
};
Expand Down