diff options
Diffstat (limited to 'service/pixelated')
-rw-r--r-- | service/pixelated/adapter/services/mail_service.py | 5 | ||||
-rw-r--r-- | service/pixelated/adapter/services/mailboxes.py | 8 | ||||
-rw-r--r-- | service/pixelated/certificates/dev.pixelated-project.org.ca.crt | 62 | ||||
-rw-r--r-- | service/pixelated/certificates/dev.wazokazi.is.ca.crt | 33 | ||||
-rw-r--r-- | service/pixelated/certificates/example.wazokazi.is.ca.crt | 32 | ||||
-rw-r--r-- | service/pixelated/maintenance.py | 195 | ||||
-rw-r--r-- | service/pixelated/resources/mails_resource.py | 15 |
7 files changed, 181 insertions, 169 deletions
diff --git a/service/pixelated/adapter/services/mail_service.py b/service/pixelated/adapter/services/mail_service.py index 03889f82..656bb4bc 100644 --- a/service/pixelated/adapter/services/mail_service.py +++ b/service/pixelated/adapter/services/mail_service.py @@ -97,6 +97,11 @@ class MailService(object): trashed_mail = self.mailboxes.move_to_trash(mail_id) self.search_engine.index_mail(trashed_mail) + def recover_mail(self, mail_id): + mail = self.mail(mail_id) + recovered_mail = self.mailboxes.move_to_inbox(mail_id) + self.search_engine.index_mail(recovered_mail) + def delete_permanent(self, mail_id): mail = self.mail(mail_id) self.search_engine.remove_from_index(mail_id) diff --git a/service/pixelated/adapter/services/mailboxes.py b/service/pixelated/adapter/services/mailboxes.py index a7a3a591..e9fe6ce5 100644 --- a/service/pixelated/adapter/services/mailboxes.py +++ b/service/pixelated/adapter/services/mailboxes.py @@ -49,8 +49,14 @@ class Mailboxes(object): return [self._create_or_get(leap_mailbox_name) for leap_mailbox_name in self.account.mailboxes] def move_to_trash(self, mail_id): + return self._move_to(mail_id, self.trash()) + + def move_to_inbox(self, mail_id): + return self._move_to(mail_id, self.inbox()) + + def _move_to(self, mail_id, mailbox): mail = self.querier.mail(mail_id) - mail.set_mailbox(self.trash().mailbox_name) + mail.set_mailbox(mailbox.mailbox_name) mail.save() return mail diff --git a/service/pixelated/certificates/dev.pixelated-project.org.ca.crt b/service/pixelated/certificates/dev.pixelated-project.org.ca.crt index 8f2219a7..22ccb662 100644 --- a/service/pixelated/certificates/dev.pixelated-project.org.ca.crt +++ b/service/pixelated/certificates/dev.pixelated-project.org.ca.crt @@ -1,33 +1,33 @@ -----BEGIN CERTIFICATE----- -MIIFozCCA4ugAwIBAgIBATANBgkqhkiG9w0BAQ0FADBkMRYwFAYDVQQKDA1kZXYu -cGl4ZWxhdGVkMSowKAYDVQQLDCFodHRwczovL2Rldi5waXhlbGF0ZWQtcHJvamVj -dC5vcmcxHjAcBgNVBAMMFWRldi5waXhlbGF0ZWQgUm9vdCBDQTAeFw0xNTAxMjAw -MDAwMDBaFw0yNTAxMjAwMDAwMDBaMGQxFjAUBgNVBAoMDWRldi5waXhlbGF0ZWQx -KjAoBgNVBAsMIWh0dHBzOi8vZGV2LnBpeGVsYXRlZC1wcm9qZWN0Lm9yZzEeMBwG -A1UEAwwVZGV2LnBpeGVsYXRlZCBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOC -Ag8AMIICCgKCAgEAnhlrDaixEGkzugWvwp1pPq4UUq8lWSLe173IHRvuElckYmEy -qTG/UpHx7ZAG/6OLNoCavOO4SEZvYGfGKRpqWGAm8O1acFc7S5GSOJcQQ5UO6bj8 -/32x3/wQAm85T1yUYAgJG0EWExheKMkQVXsRrXuYPsJJ6t3R33nQMUouJCY2toUb -Nu2NAhCZSNxL/77akwznYwtOS2aupznH4nzsxI70y9WlUcSIqlISJW9S65CMnIVq -xgtAxDZ+XOoYrS7Ihh87Dge8eWaUaTOTf+TgyLwxO0v3r64/tjnAV+jDzQsQKnhw -HNNOi2X7E85DzdicB+HOz8mP7G4LiLeCUGGiKQ4CcG7LCMBVcaUWpig7TBQT1PgL -JGwqSw98TD5+81mgU4sjC85HRngGRtoeWkjkLE5jXntFd6S7sUUctJ1CIMJN+W2P -D3g0TQp2mX8OY9zhyX87Lbc/YPY3+OHHtlKm/Gey+LplfWG65i7sPhzWYO/8gmML -nZeuwK4nm21aT3ugonnKiMetmFNDlMH2JxLg+pmw2BnwJe8jNYD6i8wDHTb6mYxU -iMJyU7KPIWXOznNTVwn3c2CBijzfmsbtuyswk7RePpXhHlLzgsw0tb0OlnO3EQKQ -7O4FLZO5erpa5ANb9j4/9MYJlfXQHPvhI2dsr3yv893/7fEK0AeuguqLQMMCAwEA -AaNgMF4wHQYDVR0OBBYEFGuiVuLgAlxTj8o7g+Nl8MhODLb1MA4GA1UdDwEB/wQE -AwICBDAMBgNVHRMEBTADAQH/MB8GA1UdIwQYMBaAFGuiVuLgAlxTj8o7g+Nl8MhO -DLb1MA0GCSqGSIb3DQEBDQUAA4ICAQBXd2dgIe4DCKS9BECJoJAanf73cmzgAcUc -dfW2MhppAe3CscL8N4MJSxgJz+HUjmoNNUHpNLxRuigkarYqJxhLh1YvoyfvLJ/l -8+FvHsb3w3S4T1fDhmdnMp04niFUgDvDFgjaeVVg9WVelmAIKsGZZhNMmqqScS+T -uJuSIT/TZmLEcT2QqPVPZEFfT6IsZRgdgKpRw237bhP8TayzSvpsFbwUuVNXbOEc -IPj/rGdzAJWTWC+EVdVBKw3bcNrYoXEkWEtlchsw8uhHuAYOCaf2t5WjZVOwKmQ5 -o9vFP2yWNg1+OxKnHkJupnUbLVCx1qoRJ5M5f7zNOoyr9G6VEb6v+TlFVfSWqXQs -gj/Iy3q4Y9rgdA/4u6V3LdjJgZSFfSHKePeHZuGqKTnY9MxLwARkRfte3/TNFJLe -GdIOaKe236Rf28PYfinBqujhqhlJKWPVJSF1idR0F0jcWXRTPb3bR+0YP0tJXLtS -ICzsgv92LOkUjet1vcJrrLoJMnA27MqZNzClzP+Lrh1JtxA8w8wXTNal6oQbw8sZ -iO1+sca3wifjr4Fh/63ka52dTLDQB++CKkR7vffq8tBUoILxJ0vmiFcVdWWrjJnN -qdAVWM7CTclo/kscqoYDobIusaw/pouyyIdLYHPROlGIObxcr6jBlOvPoPn5gHzi -UBl/Dd7yAQ== +MIIFqzCCA5OgAwIBAgIBATANBgkqhkiG9w0BAQ0FADBoMRowGAYDVQQKDBFQaXhl +bGF0ZWQgUHJvamVjdDEmMCQGA1UECwwdaHR0cHM6Ly9waXhlbGF0ZWQtcHJvamVj +dC5vcmcxIjAgBgNVBAMMGVBpeGVsYXRlZCBQcm9qZWN0IFJvb3QgQ0EwHhcNMTUw +NDAxMDAwMDAwWhcNMjUwNDAxMDAwMDAwWjBoMRowGAYDVQQKDBFQaXhlbGF0ZWQg +UHJvamVjdDEmMCQGA1UECwwdaHR0cHM6Ly9waXhlbGF0ZWQtcHJvamVjdC5vcmcx +IjAgBgNVBAMMGVBpeGVsYXRlZCBQcm9qZWN0IFJvb3QgQ0EwggIiMA0GCSqGSIb3 +DQEBAQUAA4ICDwAwggIKAoICAQDIKlYvQciyw1gq7NgyXxo4OPnlB6cyjLb0vr6V +cnY00F3pwa3cuOASYtZ5p4IMGod1fZoBUlGFbxay0NO/FyOlPVc3FaF1cL5oYurl +a/koAjAihGMGEjsc2gcdODJOHoidgZG4a4WUCVfXP54QFkG6tXve1uWnZAt7W6Z8 +M4DobBqh4HE8aAn1vSIdOltKvuH6Jz9+O2SZdXczEKuHM/Zv8o5qI4+3CKQ/enLS +WUfqZx217zJw4xax4kTsZxaU56XkdXGjAoqKmP3am8sAfSPyt5J6yPvKzUM2hbyQ +v/ZR3AzKX6E5w/kPWfrjr+ABPtMEbcUEQYTR5Ic/46umzseEEUTHaeBhn5XZfan/ +K3+iOXHgukuNX5BF28D10RKrIWutOr6pMWXtFNLsmSvbii6SYg4sr80RhPsox3Lf +QuO36aH/jrkmyeEgTVVyniPUYLeg/IU+lQzOQpoHR7FiS2/39QP9HNbO7kQzi2Fh +aFQW35sRRZuz+Gt38y0DObKOwEZaR2NM2kIHiR6cYWP9fYCekOfJi7rp0hfxcO+J +o+kVoZM53SS0QJGzHnKYo+hHAy01Hj9Kh7N269rruZSjDXsWF/eZp5oYQeItBolq +J3Va8VyQk12Pd+4vcIERWNx8JCBDnYY1+sRBsrsH1mSMRQxOkbOhlx0y64dRNQRa +GV4xxQIDAQABo2AwXjAdBgNVHQ4EFgQUdXb2FIbWofTZ00R/OoQQu2K1mscwDgYD +VR0PAQH/BAQDAgIEMAwGA1UdEwQFMAMBAf8wHwYDVR0jBBgwFoAUdXb2FIbWofTZ +00R/OoQQu2K1mscwDQYJKoZIhvcNAQENBQADggIBAKR6XuNIZGWccQtVxuOKRuNY +5KE5N2Gqi4erN1XkJvOD60an2F6aYjFUN1ZZfq31Oi57GHZ8lwPKZZuAn/pn2vQG +1YpGFXndnoFkKDGb3XVRMHMtFIcV/2u2rX8zfRmZGpHvgSZo+9g4PN2jCipKkuki +pVnLjO7SZi4/AAuzlFPBUHE441xJI6Hl3lLKFezLD4akxrBpFbW+rBOSFupxyBcD +hedH0MyHY6HUQLL4Mm2tobouFStUcBZT0wGEeh/tlaJKAhk/kzryle4IZcqpv01a +6BfsyO9kRABc4b9w26tvd93utgXkpmwni+I31QSFVH/s8oU1pYvrpHO2MQf5rE7X +gyVvUaXSNETE2Nj1/Bp0Bbk/A2IyzOyoIALU+5LBOzgnW8K+Ojg9FQSRuIFZF+fw +VRruRFMziKtFBYaTclWX9mf+tn3MFSe8FcIcpMa0yXu9pDtQxZeeFG/TbseE0VjS +20HHEPnA6YIKbi7vg7LZP+dZoPBc30tJeG/fDCo6EDmFhddtDJpmnFPnr3OVf1AC +B90gGoXQ2RJsP8ZLkYlMn5JYKQbXLQSf806eMYJr3Mo6IBOR+o9dxAyBtEBgAUG6 +jgfKRzGizhHA3LDbxUlJt1k16SU58QBY3p8FHwjbjon7GDEOhSNOtuHAHUc83sHH +SC1pIYpuR4H4lTW5fuyF -----END CERTIFICATE----- diff --git a/service/pixelated/certificates/dev.wazokazi.is.ca.crt b/service/pixelated/certificates/dev.wazokazi.is.ca.crt deleted file mode 100644 index 0fda59da..00000000 --- a/service/pixelated/certificates/dev.wazokazi.is.ca.crt +++ /dev/null @@ -1,33 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFnzCCA4egAwIBAgIBATANBgkqhkiG9w0BAQ0FADBiMRowGAYDVQQKDBFQaXhl -bGF0ZWRfU3RhZ2luZzEgMB4GA1UECwwXaHR0cHM6Ly9kZXYud2F6b2themkuaXMx -IjAgBgNVBAMMGVBpeGVsYXRlZF9TdGFnaW5nIFJvb3QgQ0EwHhcNMTQxMDIyMDAw -MDAwWhcNMjQxMDIyMDAwMDAwWjBiMRowGAYDVQQKDBFQaXhlbGF0ZWRfU3RhZ2lu -ZzEgMB4GA1UECwwXaHR0cHM6Ly9kZXYud2F6b2themkuaXMxIjAgBgNVBAMMGVBp -eGVsYXRlZF9TdGFnaW5nIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw -ggIKAoICAQC541dNmfzVEzLZ0LdV5ASG1STjB9NgoPpCily1bjjWhnglhNHEAfvP -kj2uEGXJip/ndJB/RV4QSqqxgoq8aHfhIspYLZ0IG5pIFnjdIMB5brqpkkf5N2wY -tSFy2gkspx/hk6xnEGyxDQntraY5rqFRLjCAE+cwk9kbqlm8iRrPApMDODizsNKF -8sTW/gC7U/LAkTvzZdnCUg4i72SmBUnZmudXiTiRTnvf2gmdCrPY2tpEguyWh+NB -qeig6wju0NGZl7+y7MnshteEcJ9IMiao88SRvL8B4pK8gA60ix+06QIPmuh8wQac -+rCB1+3sjeOSrBVPXzQkgLWqu/rT551AyKAEQsCm6SKPs/PhcLaZPLfA/onuZMdO -NL8l1DeRyyAXQYZgRMM4P0PUEmVfhV/xmkR62bhuQ8hvXV4lmhRSPqB5Whb0PNJ4 -SuGJTL6hu1b+zNBFqGl4EX/itYLS6anqmR8cIgallfkTOUgunOOUwzoj8hVDrbJF -6cWld0PmtFgUh5vaIpKZ+ygOLEosVqBVZzzN4ObEh+MfIxpzYZJ2ylB2r8DVzDxq -55G0f7LZHL31WcJwVF4lfmz1rx8us83DCWXJcVpxgJpoo/+Z+hyiUFf/XCMNYXn9 -vgZ1+bO7k/zUXGf+rnCgTxQkGTPZ95CCZ1nIMl7RgIJrSirBnlV5hQIDAQABo2Aw -XjAdBgNVHQ4EFgQUCSvehLZHfFbYbEhsNfWin8KNf6MwDgYDVR0PAQH/BAQDAgIE -MAwGA1UdEwQFMAMBAf8wHwYDVR0jBBgwFoAUCSvehLZHfFbYbEhsNfWin8KNf6Mw -DQYJKoZIhvcNAQENBQADggIBAJRD90EJ+zUOFA3Ky7NdNao3JXNLNIVsXTO5FAAM -ZPMeoSKIdKES5kc0vKlswP6RT7tBY5EH6sdjFMGEPK9glgxI1An4ozmgBUndOrql -mab9Ep+9ckfof8Yg6foETkpg6YhdWLbIHs98ajiTY6bozW1jJaRceVf57JLycqcO -FuEJ1fHRMqy2CY96g/Z4bMqkkYkVJKkyv7NIHg//DvRvboB4h+hO0MRB6rPAFC63 -6wxpGYhH4LHWRGS54IKwQxsOxpX38VM67Zj0XSEIx77b2E45unRXoZRwCBEWJlcv -5QWPCDxJgi0hDH1Fer+vQlcjB6/Kzg8AiVD15qGSNMLcjzn2Z334m0ErcYFI/c3A -VAMzCBR40mJx6r2zHUYbo+rR23huRWuFgeIdeeOJnJzpb+GwuGHlCdPl7mb7G8lp -R/U6J+GSUWs55quasE3VimDtX6eqh94HakGuq4n596GsIhYu6YHVSAf/4uTenpDk -ux2qIoSjZlarhoUoayRti4/HcP2a0w604jmyFLPNTi59J/xz/wwc7z8xwAT9DZ6F -4yxCC+u/eePbQY0USTRlrNIF9hi9DeJOxr/lTDZ8iXMxN820QiixH0XRQPrGEMcp -oY0FiYBJHweeaSEqz3AYB6updct7Qi0yS4g1uE8M9m+6SNzmSVpQWmZPr7iM5Cua -e0TX ------END CERTIFICATE----- diff --git a/service/pixelated/certificates/example.wazokazi.is.ca.crt b/service/pixelated/certificates/example.wazokazi.is.ca.crt deleted file mode 100644 index 515a12c4..00000000 --- a/service/pixelated/certificates/example.wazokazi.is.ca.crt +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFkzCCA3ugAwIBAgIBATANBgkqhkiG9w0BAQ0FADBcMRUwEwYDVQQKDAxMRUFQ -X0V4YW1wbGUxJDAiBgNVBAsMG2h0dHBzOi8vZXhhbXBsZS53YXpva2F6aS5pczEd -MBsGA1UEAwwUTEVBUF9FeGFtcGxlIFJvb3QgQ0EwHhcNMTQxMDMxMDAwMDAwWhcN -MjQxMDMxMDAwMDAwWjBcMRUwEwYDVQQKDAxMRUFQX0V4YW1wbGUxJDAiBgNVBAsM -G2h0dHBzOi8vZXhhbXBsZS53YXpva2F6aS5pczEdMBsGA1UEAwwUTEVBUF9FeGFt -cGxlIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsbVir -UZrbwQ6MLPY8i9KrYpCnFnYPTCZez6kfK0S9+5IVNltZlbedYPN/Mjr3ngdo4tSl -fZK6bk3UX1JhL6GkMMXD8Nk/yckGwaV9IbLdNI5Ihu3ot/SYIV8Bst19+hWUFbtN -Qgwlkyla2ZAqH6pIL7Hc5vED0ouVN5CBErYxsm/+mj5p69BtCZoR0QaKWURF2rTx -COb+xrhMRmqg/JPcsEtK/OqgIplkbjsHfxsknutFE6l/FbFvxc0sSmaMyd6fCVM4 -y9ivZXXh376klYPMuO0fXkGd79gSbWGldcX3MVbFNfwp2SxPXc/zP8/ntg0kqN4R -hASAvsT1bMG9/elXmU5XGouaJ0x5utK9/49qzfKiGyu/hW/ihQsGMx6I05EGxnsL -NFfUooySUqy6bB9BliHgyBaHHToNMJH2LHiyYFANWT6rPWAMH7VKEohNMRxu5IRK -U0E5OwSXu4yI5JU4bviuGSe93V5OOmO6GeIxVupij5i/1XtJ1Z5skuBcq7b7C2/6 -zNKoEu/wE9lbtjPNl7JwIYjaWRLpI+bMDPWjBSDSLCkHXPuxOCWFggGMEPOI4d3J -5hp22UGQxqq7z86ZTxPfx9Ce9oUbl1NOkuNznc0XVjFcglHqz4/75ogNP0dmra+P -GmPoAetOlKOIXxbBOQeSJr4WAgQK3GECb3uvQQIDAQABo2AwXjAdBgNVHQ4EFgQU -ti27+d3zDOJiJeQyx6il6YzZkKowDgYDVR0PAQH/BAQDAgIEMAwGA1UdEwQFMAMB -Af8wHwYDVR0jBBgwFoAUti27+d3zDOJiJeQyx6il6YzZkKowDQYJKoZIhvcNAQEN -BQADggIBABMGDact+sxOf8Yyt+mzckf1uANEw3TAM81ztxuiwYA6/quNvBISdjS6 -PyyZ8S3U+sjJA5FQW1SDd4IbuRFK2Y2Hmeto1uIFAxjQj/jDdW26Wj/FkBmWnCQd -L2/CSU1MXitLuxHE8SaUWrw+W7I/Ga5t+9VRxDI0XNF+OAEPwvp6JequZKIW+OcT -4fU7z4xu2QYSPRVzliJ9fVxb4jllG6kLNLnqkVTQNiOJ8sVbALh1tJSSFGd6ZGNB -8ePrWkPOyYMD6J+zy6uqDTUipaXuVIgA7mPTyu0XKqWO3tZXyakITlxnHgMYqpfE -XNkGArsMNXV3ktp+HCpGVO46+9nMzSPIBxMfpgpeq3ommBov3pANT0S5IrBiyo/T -VjUkWz3D1ymRyK0SWrHZSOq9rUS+tMjKxwmhFTBn1cR7PItWB9pNiVt/Oz0z1ecM -Ij4pMb/jPvV2H6crMjMVSPzbazTE/S6AEl0beZ/o44Frz1aXvuMwgtG6fUFZma4X -6exBWOmqF96qkPH2I0olHIbOTXHz+uBKJnFaSg09RT+AZfFutJ2DkVK7NJgOdyjf -QQcDfkfeRz/A6mI5wjm/UwZRWWytBuUDjU4ZaqxH9AlmzXsJHoYYr0YgTEYlm16o -eGTyR4QlaLlwTg1CvZgHTKxpI/LKn1T4aMHHvd92W2fT7pq4PWlH ------END CERTIFICATE----- diff --git a/service/pixelated/maintenance.py b/service/pixelated/maintenance.py index 8c20e097..b4e616a7 100644 --- a/service/pixelated/maintenance.py +++ b/service/pixelated/maintenance.py @@ -1,4 +1,4 @@ -# + # Copyright (c) 2014 ThoughtWorks, Inc. # # Pixelated is free software: you can redistribute it and/or modify @@ -20,9 +20,10 @@ import sys import json import argparse import email +import re from os.path import join -from mailbox import mboxMessage +from mailbox import mboxMessage, Maildir from pixelated.config.app import App from pixelated.config import app_factory from pixelated.config.args import parser_add_default_arguments @@ -39,6 +40,7 @@ from twisted.internet.threads import deferToThread from leap.mail.imap.memorystore import MemoryStore from leap.mail.imap.soledadstore import SoledadStore +from leap.mail.imap.fields import WithMsgFields from leap.common.events import register, unregister, events_pb2 as proto # monkey patching some specifics @@ -50,51 +52,26 @@ import pixelated.support.ext_keymanager_fetch_key import pixelated.support.ext_requests_urllib3 -def delete_all_mails(args): - leap_session, soledad = args - generation, docs = soledad.get_all_docs() - - for doc in docs: - if doc.content.get('type', None) in ['head', 'cnt', 'flags']: - soledad.delete_doc(doc) - - return args - - -@defer.inlineCallbacks -def load_mails(args, mail_paths): - leap_session, soledad = args - account = leap_session.account - - for path in mail_paths: - print 'Loading mails from %s' % path - for root, dirs, files in os.walk(path): - mbx = account.getMailbox('INBOX') - for f in files: - with open(join(root, f), 'r') as fp: - m = email.message_from_file(fp) - flags = ("\\RECENT",) - r = yield mbx.addMessage(m.as_string(), flags=flags, notify_on_disk=False) - print 'Added message %s' % m.get('subject') - print m.as_string() - - defer.returnValue(args) - return - +def initialize(): + args = parse_args() + app = App() -def dump_soledad(args): - leap_session, soledad = args + init_logging(args) + init_leap_cert(args) - generation, docs = soledad.get_all_docs() + if args.dispatcher or args.dispatcher_stdin: + config_dispatcher(app, args) + else: + config_user_agent(app, args) - for doc in docs: - print doc - print '\n' + init_events_server() + execute_command = create_execute_command(args, app) - return args + reactor.callWhenRunning(execute_command) + reactor.run() -def initialize(): +def parse_args(): parser = argparse.ArgumentParser(description='pixelated maintenance') parser_add_default_arguments(parser) subparsers = parser.add_subparsers(help='commands', dest='command') @@ -105,19 +82,10 @@ def initialize(): subparsers.add_parser('dump-soledad', help='dump the soledad database') subparsers.add_parser('sync', help='sync the soledad database') - args = parser.parse_args() - app = App() - - init_logging(args) - init_leap_cert(args) - - if args.dispatcher or args.dispatcher_stdin: - config_dispatcher(app, args) - else: - config_user_agent(app, args) + return parser.parse_args() - init_events_server() +def create_execute_command(args, app): def execute_command(): def init_soledad(): @@ -135,26 +103,109 @@ def initialize(): return args - d = deferToThread(init_soledad) - d.addCallback(get_soledad_handle) - d.addCallback(soledad_sync) - if args.command == 'reset': - d.addCallback(delete_all_mails) - elif args.command == 'load-mails': - d.addCallback(load_mails, args.file) - elif args.command == 'dump-soledad': - d.addCallback(dump_soledad) - elif args.command == 'sync': - # nothing to do here, sync is already part of the chain - pass + tearDown = defer.Deferred() + + prepare = deferToThread(init_soledad) + prepare.addCallback(get_soledad_handle) + prepare.addCallback(soledad_sync) + add_command_callback(args, prepare, tearDown) + tearDown.addCallback(soledad_sync) + tearDown.addCallback(shutdown) + tearDown.addErrback(shutdown_on_error) + + return execute_command + + +def add_command_callback(args, prepareDeferred, finalizeDeferred): + if args.command == 'reset': + prepareDeferred.addCallback(delete_all_mails) + prepareDeferred.addCallback(flush_to_soledad, finalizeDeferred) + elif args.command == 'load-mails': + prepareDeferred.addCallback(load_mails, args.file) + prepareDeferred.addCallback(flush_to_soledad, finalizeDeferred) + elif args.command == 'dump-soledad': + prepareDeferred.addCallback(dump_soledad) + prepareDeferred.chainDeferred(finalizeDeferred) + elif args.command == 'sync': + # nothing to do here, sync is already part of the chain + prepareDeferred.chainDeferred(finalizeDeferred) + else: + print 'Unsupported command: %s' % args.command + prepareDeferred.chainDeferred(finalizeDeferred) + + return finalizeDeferred + + +def delete_all_mails(args): + leap_session, soledad = args + generation, docs = soledad.get_all_docs() + + for doc in docs: + if doc.content.get('type', None) in ['head', 'cnt', 'flags']: + soledad.delete_doc(doc) + + return args + + +def add_mail_folder(account, maildir, folder_name, deferreds): + mbx = account.getMailbox(folder_name) + for mail in maildir: + flags = (WithMsgFields.RECENT_FLAG,) if mail.get_subdir() == 'new' else () + if 'S' in mail.get_flags(): + flags = (WithMsgFields.SEEN_FLAG,) + flags + if 'R' in mail.get_flags(): + flags = (WithMsgFields.ANSWERED_FLAG,) + flags + + deferreds.append(mbx.addMessage(mail.as_string(), flags=flags, notify_on_disk=False)) + + +@defer.inlineCallbacks +def load_mails(args, mail_paths): + leap_session, soledad = args + account = leap_session.account + + deferreds = [] + + for path in mail_paths: + maildir = Maildir(path, factory=None) + add_mail_folder(account, maildir, 'INBOX', deferreds) + for mail_folder_name in maildir.list_folders(): + mail_folder = maildir.get_folder(mail_folder_name) + add_mail_folder(account, mail_folder, mail_folder_name, deferreds) + + yield defer.DeferredList(deferreds) + defer.returnValue(args) + + +def flush_to_soledad(args, finalize): + leap_session, soledad = args + account = leap_session.account + memstore = account._memstore + permanent_store = memstore._permanent_store + + d = memstore.write_messages(permanent_store) + + def check_flushed(args): + if memstore.is_writing: + reactor.callLater(1, check_flushed, args) else: - print 'Unsupported command: %s' % args.command - d.addCallback(soledad_sync) - d.addCallback(shutdown) - d.addErrback(shutdown_on_error) + finalize.callback((leap_session, soledad)) - reactor.callWhenRunning(execute_command) - reactor.run() + d.addCallback(check_flushed) + + return args + + +def dump_soledad(args): + leap_session, soledad = args + + generation, docs = soledad.get_all_docs() + + for doc in docs: + print doc + print '\n' + + return args def shutdown(args): @@ -163,7 +214,7 @@ def shutdown(args): def shutdown_on_error(error): print error - reactor.stop() + shutdown(None) -if __name__ == 'main': +if __name__ == '__main__': initialize() diff --git a/service/pixelated/resources/mails_resource.py b/service/pixelated/resources/mails_resource.py index c057031a..3822abd3 100644 --- a/service/pixelated/resources/mails_resource.py +++ b/service/pixelated/resources/mails_resource.py @@ -53,6 +53,20 @@ class MailsDeleteResource(Resource): return respond_json(None, request) +class MailsRecoverResource(Resource): + isLeaf = True + + def __init__(self, mail_service): + Resource.__init__(self) + self._mail_service = mail_service + + def render_POST(self, request): + idents = json.loads(request.content.read())['idents'] + for ident in idents: + self._mail_service.recover_mail(ident) + return respond_json(None, request) + + class MailsResource(Resource): def _register_smtp_error_handler(self): @@ -66,6 +80,7 @@ class MailsResource(Resource): def __init__(self, mail_service, draft_service): Resource.__init__(self) self.putChild('delete', MailsDeleteResource(mail_service)) + self.putChild('recover', MailsRecoverResource(mail_service)) self.putChild('read', MailsReadResource(mail_service)) self.putChild('unread', MailsUnreadResource(mail_service)) |