1+ import imaplib
12import ipaddress
3+ import smtplib
4+ import ssl
5+ from email .mime .text import MIMEText
26
37import imap_tools
8+ import pytest
49import requests
510
611
@@ -27,6 +32,18 @@ def test_one_on_one(self, cmfactory, lp):
2732 msg2 = ac2 .wait_for_incoming_msg ()
2833 assert msg2 .get_snapshot ().text == "message0"
2934
35+ def test_send_dot (self , cmfactory , lp ):
36+ """Test that a single dot is properly escaped in SMTP protocol"""
37+ ac1 , ac2 = cmfactory .get_online_accounts (2 )
38+ chat = cmfactory .get_accepted_chat (ac1 , ac2 )
39+
40+ lp .sec ("ac1: sending single dot message" )
41+ chat .send_text ("." )
42+
43+ lp .sec ("ac2: wait for receive" )
44+ msg2 = ac2 .wait_for_incoming_msg ()
45+ assert msg2 .get_snapshot ().text == "."
46+
3047
3148class TestMultiRelay :
3249 """Tests that use two different chatmail relays."""
@@ -73,3 +90,44 @@ def test_hide_senders_ip_address(cmfactory, ssl_context):
7390 msgs = list (mailbox .fetch (mark_seen = False ))
7491 assert msgs , "expected at least one message"
7592 assert public_ip not in msgs [0 ].obj .as_string ()
93+
94+
95+ def test_unencrypted_rejection (cmsetup , lp ):
96+ """Test that unencrypted messages are rejected by the relay."""
97+ lp .sec ("creating users" )
98+ u1 , u2 = cmsetup .gen_users (2 )
99+
100+ lp .sec ("sending unencrypted mail via SMTP" )
101+ msg = MIMEText ("unencrypted" )
102+ msg ["Subject" ] = "test"
103+ msg ["From" ] = u1 .addr
104+ msg ["To" ] = u2 .addr
105+
106+ try :
107+ u1 .smtp .sendmail (u1 .addr , [u2 .addr ], msg .as_string ())
108+ pytest .fail ("Unencrypted message was accepted!" )
109+ except smtplib .SMTPDataError as e :
110+ assert e .smtp_code == 523
111+ except smtplib .SMTPRecipientsRefused as e :
112+ for addr , (code , msg ) in e .recipients .items ():
113+ assert code == 523
114+
115+
116+ def test_login_domain_validation (maildomain , lp ):
117+ """Test that IMAP LOGIN validates the domain part for JIT creation."""
118+ lp .sec ("attempting login with invalid domain" )
119+ # We use raw imaplib because cmsetup.gen_users() would fail at credential generation
120+ # or handle the error differently.
121+ user = f"invalid@{ maildomain } .invalid"
122+
123+ ctx = ssl .create_default_context ()
124+ ctx .check_hostname = False
125+ ctx .verify_mode = ssl .CERT_NONE
126+
127+ with imaplib .IMAP4_SSL (maildomain , ssl_context = ctx ) as conn :
128+ try :
129+ conn .login (user , "password" )
130+ pytest .fail ("Login with invalid domain was accepted!" )
131+ except imaplib .IMAP4 .error as e :
132+ # Most relays return [AUTHENTICATIONFAILED] or similar
133+ assert "FAILED" in str (e ) or "Invalid" in str (e )
0 commit comments