summaryrefslogtreecommitdiff
path: root/service/pixelated
diff options
context:
space:
mode:
Diffstat (limited to 'service/pixelated')
-rw-r--r--service/pixelated/adapter/services/mail_service.py5
-rw-r--r--service/pixelated/adapter/services/mailboxes.py8
-rw-r--r--service/pixelated/certificates/dev.pixelated-project.org.ca.crt62
-rw-r--r--service/pixelated/certificates/dev.wazokazi.is.ca.crt33
-rw-r--r--service/pixelated/certificates/example.wazokazi.is.ca.crt32
-rw-r--r--service/pixelated/maintenance.py195
-rw-r--r--service/pixelated/resources/mails_resource.py15
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))