mirror of
https://github.com/chatmail/core.git
synced 2026-04-06 07:32:12 +03:00
@@ -28,7 +28,7 @@ class Account(object):
|
||||
"""
|
||||
MissingCredentials = MissingCredentials
|
||||
|
||||
def __init__(self, db_path, os_name=None, logging=True):
|
||||
def __init__(self, db_path, os_name=None, logging=True, logid=None):
|
||||
""" initialize account object.
|
||||
|
||||
:param db_path: a path to the account database. The database
|
||||
@@ -38,6 +38,7 @@ class Account(object):
|
||||
# initialize per-account plugin system
|
||||
self._pm = hookspec.PerAccount._make_plugin_manager()
|
||||
self._logging = logging
|
||||
self.logid = logid
|
||||
|
||||
self.add_account_plugin(self)
|
||||
|
||||
|
||||
141
python/src/deltachat/direct_imap.py
Normal file
141
python/src/deltachat/direct_imap.py
Normal file
@@ -0,0 +1,141 @@
|
||||
import imaplib
|
||||
import pathlib
|
||||
from . import Account
|
||||
|
||||
INBOX = "Inbox"
|
||||
SENT = "Sent"
|
||||
MVBOX = "DeltaChat"
|
||||
MVBOX_FALLBBACK = "INBOX/DeltaChat"
|
||||
DC_CONSTANT_MSG_MOVESTATE_PENDING = 1
|
||||
DC_CONSTANT_MSG_MOVESTATE_STAY = 2
|
||||
DC_CONSTANT_MSG_MOVESTATE_MOVING = 3
|
||||
|
||||
|
||||
def db_folder_attr(name):
|
||||
def fget(s):
|
||||
return s.db_folder.get(name, 1)
|
||||
|
||||
def fset(s, val):
|
||||
s.db_folder[name] = val
|
||||
return property(fget, fset, None, None)
|
||||
|
||||
|
||||
class ImapConn():
|
||||
def __init__(self, foldername, conn_info):
|
||||
self.foldername = foldername
|
||||
host, user, pw = conn_info
|
||||
|
||||
self.connection = imaplib.IMAP4_SSL(host)
|
||||
self.connection.login(user, pw)
|
||||
messages = self.reselect_folder()
|
||||
try:
|
||||
self.original_msg_count = int(messages[0])
|
||||
except IndexError:
|
||||
self.original_msg_count = 0
|
||||
|
||||
def mark_all_read(self):
|
||||
self.reselect_folder()
|
||||
# result, data = self.connection.uid('search', None, "(UNSEEN)")
|
||||
result, data = self.connection.search(None, 'UnSeen')
|
||||
try:
|
||||
mails_uid = data[0].split()
|
||||
print("New mails")
|
||||
|
||||
# self.connection.store(data[0].replace(' ',','),'+FLAGS','\Seen')
|
||||
for e_id in mails_uid:
|
||||
self.connection.store(e_id, '+FLAGS', '\\Seen')
|
||||
print("marked:", e_id)
|
||||
|
||||
return True
|
||||
except IndexError:
|
||||
print("No unread")
|
||||
return False
|
||||
|
||||
def get_unread_cnt(self):
|
||||
self.reselect_folder()
|
||||
# result, data = self.connection.uid('search', None, "(UNSEEN)")
|
||||
result, data = self.connection.search(None, 'UnSeen')
|
||||
try:
|
||||
mails_uid = data[0].split()
|
||||
|
||||
return len(mails_uid)
|
||||
except IndexError:
|
||||
return 0
|
||||
|
||||
def get_new_email_cnt(self):
|
||||
messages = self.reselect_folder()
|
||||
try:
|
||||
return int(messages[0]) - self.original_msg_count
|
||||
except IndexError:
|
||||
return 0
|
||||
|
||||
def reselect_folder(self):
|
||||
status, messages = self.connection.select(self.foldername)
|
||||
if status != "OK":
|
||||
print("Incorrect mail box " + status + str(messages))
|
||||
raise ConnectionError
|
||||
# print("(Re-)Selected mailbox: " + status + " " + str(messages))
|
||||
return messages
|
||||
|
||||
def __del__(self):
|
||||
try:
|
||||
self.connection.close()
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
self.connection.logout()
|
||||
except Exception:
|
||||
print("Could not logout direct_imap conn")
|
||||
|
||||
|
||||
def make_direct_imap(account, folder):
|
||||
conn_info = (account.get_config("configured_mail_server"),
|
||||
account.get_config("addr"), account.get_config("mail_pw"))
|
||||
# try:
|
||||
# return ImapConn(folder, conn_info=conn_info)
|
||||
# except ConnectionError as e:
|
||||
# if folder == MVBOX:
|
||||
# account.log("Selecting " + MVBOX_FALLBBACK + " not " + MVBOX + " because connecting to the latter failed")
|
||||
# return ImapConn(MVBOX_FALLBBACK, conn_info=conn_info)
|
||||
# else:
|
||||
# raise e
|
||||
if folder == MVBOX:
|
||||
new_folder = account.get_config("configured_mvbox_folder")
|
||||
else:
|
||||
new_folder = folder
|
||||
if new_folder != folder:
|
||||
account.log("Making connection with " + new_folder + " not " + folder)
|
||||
return ImapConn(new_folder, conn_info=conn_info)
|
||||
|
||||
|
||||
def print_imap_structure(database, dir="."):
|
||||
print_imap_structure_ac(Account(database), dir)
|
||||
|
||||
|
||||
def print_imap_structure_ac(ac, dir="."):
|
||||
acinfo = ac.logid + "-" + ac.get_config("addr")
|
||||
print("================= ACCOUNT", acinfo, "=================")
|
||||
print("----------------- CONFIG: -----------------")
|
||||
print(ac.get_info())
|
||||
|
||||
for imapfolder in [INBOX, MVBOX, SENT, MVBOX_FALLBBACK]:
|
||||
try:
|
||||
imap = make_direct_imap(ac, imapfolder)
|
||||
c = imap.connection
|
||||
typ, data = c.search(None, 'ALL')
|
||||
c._get_tagged_response
|
||||
print("-----------------", imapfolder, "-----------------")
|
||||
for num in data[0].split():
|
||||
typ, data = c.fetch(num, '(RFC822)')
|
||||
body = data[0][1]
|
||||
|
||||
typ, data = c.fetch(num, '(UID FLAGS)')
|
||||
info = data[0]
|
||||
|
||||
path = pathlib.Path(dir).joinpath("IMAP-MESSAGES", acinfo, imapfolder)
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
file = path.joinpath(str(info).replace("b'", "").replace("'", "").replace("\\", ""))
|
||||
file.write_bytes(body)
|
||||
print("Message", info, "saved as", file)
|
||||
except Exception:
|
||||
pass
|
||||
@@ -12,7 +12,7 @@ import tempfile
|
||||
import pytest
|
||||
import requests
|
||||
|
||||
from . import Account, const
|
||||
from . import Account, const, direct_imap
|
||||
from .capi import lib
|
||||
from .events import FFIEventLogger, FFIEventTracker
|
||||
from _pytest._code import Source
|
||||
@@ -228,7 +228,7 @@ def acfactory(pytestconfig, tmpdir, request, session_liveconfig, data):
|
||||
acc.disable_logging()
|
||||
|
||||
def make_account(self, path, logid, quiet=False):
|
||||
ac = Account(path, logging=self._logging)
|
||||
ac = Account(path, logging=self._logging, logid=logid)
|
||||
ac._evtracker = ac.add_account_plugin(FFIEventTracker(ac))
|
||||
ac.addr = ac.get_self_contact().addr
|
||||
if not quiet:
|
||||
@@ -377,7 +377,10 @@ def acfactory(pytestconfig, tmpdir, request, session_liveconfig, data):
|
||||
|
||||
am = AccountMaker()
|
||||
request.addfinalizer(am.finalize)
|
||||
return am
|
||||
yield am
|
||||
if request.node.rep_call.failed:
|
||||
for ac in am._accounts:
|
||||
direct_imap.print_imap_structure_ac(ac, tmpdir)
|
||||
|
||||
|
||||
class BotProcess:
|
||||
@@ -446,3 +449,15 @@ def lp():
|
||||
def step(self, msg):
|
||||
print("-" * 5, "step " + msg, "-" * 5)
|
||||
return Printer()
|
||||
|
||||
|
||||
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
|
||||
def pytest_runtest_makereport(item, call):
|
||||
# execute all other hooks to obtain the report object
|
||||
outcome = yield
|
||||
rep = outcome.get_result()
|
||||
|
||||
# set a report attribute for each phase of a call, which can
|
||||
# be "setup", "call", "teardown"
|
||||
|
||||
setattr(item, "rep_" + rep.when, rep)
|
||||
|
||||
@@ -7,6 +7,8 @@ from deltachat import const, Account
|
||||
from deltachat.message import Message
|
||||
from deltachat.hookspec import account_hookimpl
|
||||
from datetime import datetime, timedelta
|
||||
from deltachat import direct_imap
|
||||
from deltachat.direct_imap import make_direct_imap
|
||||
|
||||
|
||||
@pytest.mark.parametrize("msgtext,res", [
|
||||
@@ -635,6 +637,83 @@ class TestOnlineAccount:
|
||||
ev_msg = ac1_clone._evtracker.wait_next_messages_changed()
|
||||
assert ev_msg.text == msg_out.text
|
||||
|
||||
@pytest.mark.parametrize('i', range(30))
|
||||
def test_mark_read_on_server(self, acfactory, lp, i):
|
||||
ac1 = acfactory.get_online_configuring_account()
|
||||
ac2 = acfactory.get_online_configuring_account(mvbox=True, move=True)
|
||||
|
||||
ac1.wait_configure_finish()
|
||||
ac1.start_io()
|
||||
ac2.wait_configure_finish()
|
||||
ac2.start_io()
|
||||
|
||||
imap2 = make_direct_imap(ac2, direct_imap.MVBOX)
|
||||
# imap2.mark_all_read()
|
||||
assert imap2.get_unread_cnt() == 0
|
||||
|
||||
chat = self.get_chat(ac1, ac2)
|
||||
chat_on_ac2 = self.get_chat(ac2, ac1)
|
||||
|
||||
chat.send_text("Text message")
|
||||
|
||||
incoming_on_ac2 = ac2._evtracker.wait_next_incoming_message()
|
||||
lp.sec("Incoming: "+incoming_on_ac2.text)
|
||||
|
||||
assert list(ac2.get_fresh_messages())
|
||||
|
||||
for i in range(0, 20):
|
||||
if imap2.get_unread_cnt() == 1:
|
||||
break
|
||||
time.sleep(1) # We might need to wait because Imaplib is slower than DC-Core
|
||||
assert imap2.get_unread_cnt() == 1
|
||||
|
||||
chat_on_ac2.mark_noticed()
|
||||
incoming_on_ac2.mark_seen()
|
||||
ac2._evtracker.wait_next_messages_changed()
|
||||
|
||||
assert not list(ac2.get_fresh_messages())
|
||||
|
||||
# The new messages should be seen now.
|
||||
for i in range(0, 20):
|
||||
if imap2.get_unread_cnt() == 0:
|
||||
break
|
||||
time.sleep(1) # We might need to wait because Imaplib is slower than DC-Core
|
||||
assert imap2.get_unread_cnt() == 0
|
||||
|
||||
@pytest.mark.parametrize('i', range(30))
|
||||
def test_mark_bcc_read_on_server(self, acfactory, lp, i):
|
||||
ac1 = acfactory.get_online_configuring_account(mvbox=True, move=True)
|
||||
ac2 = acfactory.get_online_configuring_account()
|
||||
|
||||
ac1.wait_configure_finish()
|
||||
ac1.start_io()
|
||||
ac2.wait_configure_finish()
|
||||
ac2.start_io()
|
||||
|
||||
imap1 = make_direct_imap(ac1, direct_imap.MVBOX)
|
||||
imap1.mark_all_read()
|
||||
assert imap1.get_unread_cnt() == 0
|
||||
|
||||
chat = self.get_chat(ac1, ac2)
|
||||
|
||||
ac1.set_config("bcc_self", "1")
|
||||
chat.send_text("Text message")
|
||||
|
||||
ac1._evtracker.get_matching("DC_EVENT_SMTP_MESSAGE_SENT")
|
||||
|
||||
for i in range(0, 20):
|
||||
if imap1.get_new_email_cnt() == 1:
|
||||
break
|
||||
time.sleep(1) # We might need to wait because Imaplib is slower than DC-Core
|
||||
assert imap1.get_new_email_cnt() == 1
|
||||
|
||||
for i in range(0, 20):
|
||||
if imap1.get_unread_cnt() == 0:
|
||||
break
|
||||
time.sleep(1) # We might need to wait because Imaplib is slower than DC-Core
|
||||
|
||||
assert imap1.get_unread_cnt() == 0
|
||||
|
||||
def test_send_file_twice_unicode_filename_mangling(self, tmpdir, acfactory, lp):
|
||||
ac1, ac2 = acfactory.get_two_online_accounts()
|
||||
chat = self.get_chat(ac1, ac2)
|
||||
|
||||
Reference in New Issue
Block a user