From c8fab8cd56c88d2322104afc960c836a543cd3d6 Mon Sep 17 00:00:00 2001 From: René 'Necoro' Neumann Date: Sun, 14 Mar 2010 20:02:03 +0100 Subject: Send more files for bug mails --- portato/gui/windows/mailinfo.py | 93 ++++++++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 16 deletions(-) (limited to 'portato/gui/windows/mailinfo.py') diff --git a/portato/gui/windows/mailinfo.py b/portato/gui/windows/mailinfo.py index 0ee232a..6d6e93b 100644 --- a/portato/gui/windows/mailinfo.py +++ b/portato/gui/windows/mailinfo.py @@ -14,15 +14,41 @@ from __future__ import absolute_import, with_statement import smtplib, socket import time +import gtk, pango from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText +from os.path import basename from .basic import AbstractDialog from ..utils import GtkThread from ..dialogs import mail_failure_dialog from ...helper import debug, info -from ...constants import VERSION +from ...constants import VERSION, CONFIG_LOCATION from ...log import LOGFILE +from ... import session + +class ShowDialog (gtk.Dialog): + + def __init__(self, parent, f): + gtk.Dialog.__init__(self, f, parent, buttons = (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)) + + textview = gtk.TextView() + textview.set_editable(False) + textview.modify_font(pango.FontDescription("Monospace")) + textview.set_size_request(gtk.gdk.screen_width()/2, gtk.gdk.screen_height()/3) + + sw = gtk.ScrolledWindow(); + sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + sw.add(textview) + + self.vbox.add(sw) + + textbuffer = textview.get_buffer() + + with open(f) as text: + textbuffer.set_text(text.read()) + + self.vbox.show_all() class MailInfoWindow (AbstractDialog): TO = "bugs@portato.necoro.net" @@ -30,10 +56,42 @@ class MailInfoWindow (AbstractDialog): def __init__ (self, parent, tb): AbstractDialog.__init__(self, parent) + + self.files = [LOGFILE, CONFIG_LOCATION] + [s._file for s in session.sessionlist] + self.fileList = self.tree.get_widget("fileList") + self.build_file_list() self.tb = tb self.window.show_all() + def build_file_list(self): + store = gtk.ListStore(bool, str) + + for f in self.files: + store.append((True, f)) + + self.fileList.set_model(store) + cell = gtk.CellRendererText() + tCell = gtk.CellRendererToggle() + tCell.set_property("activatable", True) + tCell.connect("toggled", self.cb_file_toggled) + + self.fileList.append_column(gtk.TreeViewColumn(None, tCell, active = 0)) + self.fileList.append_column(gtk.TreeViewColumn(None, cell, text = 1)) + + def cb_file_toggled(self, cell, path): + store = self.fileList.get_model() + store[path][0] = not store[path][0] + return True + + def cb_file_clicked(self, view, path, *args): + store = view.get_model() + f = store[path][1] + + dialog = ShowDialog(self.window, f) + dialog.run() + dialog.destroy() + def set_data (self): self.message = MIMEMultipart() self.message["Subject"] = "[Bug Report] Bug in Portato %s" % VERSION @@ -63,13 +121,15 @@ class MailInfoWindow (AbstractDialog): txtmsg = MIMEText(text, "plain", "utf-8") self.message.attach(txtmsg) - # log - if self.tree.get_widget("logCheck").get_active(): - with open(LOGFILE, "r") as f: - log = MIMEText(f.read(), "plain", "utf-8") - log.add_header('Content-Disposition', 'attachment', filename='portato.log') + # logs + for (active, f) in self.fileList.get_model(): + if active: + debug("Attaching '%s'", f) + with open(f, "r") as text: + log = MIMEText(text.read(), "plain", "utf-8") + log.add_header('Content-Disposition', 'attachment', filename=basename(f)) - self.message.attach(log) + self.message.attach(log) def send (self): try: @@ -77,21 +137,22 @@ class MailInfoWindow (AbstractDialog): server = smtplib.SMTP("mail.necoro.eu") debug("Sending mail") try: - try: - server.sendmail(self.addr, self.TO, self.message.as_string()) - except smtplib.SMTPRecipientsRefused, e: - info(_("An error occurred while sending. I think we were greylisted. The error: %s") % e) - info(_("Retrying after waiting 60 seconds.")) - time.sleep(60) - server.sendmail(self.addr, self.TO, self.message.as_string()) - debug("Sent") + for i in range(5): # try 5 times at max + try: + server.sendmail(self.addr, self.TO, self.message.as_string()) + except smtplib.SMTPRecipientsRefused, e: + info(_("An error occurred while sending. I think we were greylisted. The error: %s") % e) + info(_("Retrying after waiting %d seconds."), 30) + time.sleep(30) + else: + debug("Sent") + break finally: server.quit() except socket.error, e: mail_failure_dialog("%s (Code: %s)" % (e.args[1], e.args[0])) def cb_cancel_clicked (self, *args): - self.close() return True -- cgit v1.2.3-70-g09d2 From d772c8db351d46ed4fc9f55eb978200ebbe98307 Mon Sep 17 00:00:00 2001 From: René 'Necoro' Neumann Date: Sun, 14 Mar 2010 21:06:19 +0100 Subject: Show a dialog if no email is given --- i18n/de.po | 54 ++++++++++++++++++++++++++--------------- i18n/messages.pot | 51 +++++++++++++++++++++++--------------- portato/gui/dialogs.py | 7 ++++++ portato/gui/windows/basic.py | 3 +++ portato/gui/windows/mailinfo.py | 16 ++++++++---- 5 files changed, 87 insertions(+), 44 deletions(-) (limited to 'portato/gui/windows/mailinfo.py') diff --git a/i18n/de.po b/i18n/de.po index 88783a9..d60a707 100644 --- a/i18n/de.po +++ b/i18n/de.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: Portato\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-03-14 20:01+0100\n" -"PO-Revision-Date: 2010-03-14 20:01+0100\n" +"POT-Creation-Date: 2010-03-14 21:03+0100\n" +"PO-Revision-Date: 2010-03-14 21:04+0100\n" "Last-Translator: René 'Necoro' Neumann \n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -426,49 +426,63 @@ msgid "The error was: %s" msgstr "Der Fehler war: %s" #: portato/gui/dialogs.py:24 +msgid "No email address given" +msgstr "Keine Email-Adresse gegeben" + +#: portato/gui/dialogs.py:25 +msgid "" +"You haven't specified an email address. Without it, it will not be possible for the developers to contact you for questions and thus it might be harder to fix the bug.\n" +"\n" +"Do you want to proceed nevertheless?" +msgstr "" +"Du hast keine Email-Adresse angegeben. Daher ist es nicht möglich, dass die Entwickler dich kontaktieren können und es kann daher sein, dass der Bug schwerer zu beseitigen ist.\n" +"\n" +"Trotzdem fortfahren?" + +#: portato/gui/dialogs.py:31 msgid "Do you really want to quit?" msgstr "Wirklich beenden?" -#: portato/gui/dialogs.py:25 +#: portato/gui/dialogs.py:32 msgid "There are some packages in the emerge queue and/or an emerge process is running." msgstr "Es sind noch Pakete in der Emerge-Queue und/oder emerge läuft noch." -#: portato/gui/dialogs.py:43 +#: portato/gui/dialogs.py:50 #, python-format msgid "%(blocked)s is blocked by %(blocks)s." msgstr "%(blocks)s blockiert %(blocked)s." -#: portato/gui/dialogs.py:44 +#: portato/gui/dialogs.py:51 msgid "Please unmerge the blocking package." msgstr "Bitte deinstalliere das blockierende Paket." -#: portato/gui/dialogs.py:50 +#: portato/gui/dialogs.py:57 msgid "You are not root." msgstr "Du bist nicht root." -#: portato/gui/dialogs.py:56 +#: portato/gui/dialogs.py:63 #, python-format msgid "%s seems to be masked." msgstr "%s scheint maskiert zu sein." -#: portato/gui/dialogs.py:57 +#: portato/gui/dialogs.py:64 msgid "Do you want to unmask it and its dependencies?" msgstr "Soll das Paket und seine Abhängigkeiten demaskiert werden?" -#: portato/gui/dialogs.py:63 +#: portato/gui/dialogs.py:70 msgid "Package not found!" msgstr "Paket nicht gefunden!" -#: portato/gui/dialogs.py:69 +#: portato/gui/dialogs.py:76 msgid "Do not show this dialog again." msgstr "Diesen Dialog nicht wieder anzeigen." -#: portato/gui/dialogs.py:70 +#: portato/gui/dialogs.py:77 #, python-format msgid "Changed %s" msgstr "%s wurde geändert" -#: portato/gui/dialogs.py:71 +#: portato/gui/dialogs.py:78 msgid "" "Portato will write these changes into the appropriate files.\n" "Please backup them if you think it is necessary." @@ -476,11 +490,11 @@ msgstr "" "Portato wird diese Änderungen speichern.\n" "Bitte sichere die entsprechenden Dateien, wenn du es als notwendig erachtest." -#: portato/gui/dialogs.py:80 +#: portato/gui/dialogs.py:87 msgid "You cannot remove dependencies. :)" msgstr "Du kannst keine Abhängigkeiten löschen ;)." -#: portato/gui/dialogs.py:86 +#: portato/gui/dialogs.py:93 msgid "" "This is the updates queue. You cannot remove single elements.\n" "Do you want to clear the whole queue instead?" @@ -488,15 +502,15 @@ msgstr "" "Das ist die Update-Queue. Aus dieser können keine einzelnen Pakete entfernt werden.\n" "Soll stattdessen die komplette Queue entfernt werden?" -#: portato/gui/dialogs.py:92 +#: portato/gui/dialogs.py:99 msgid "Do you really want to clear the whole queue?" msgstr "Wirklich die gesamte Queue löschen?" -#: portato/gui/dialogs.py:111 +#: portato/gui/dialogs.py:118 msgid "A prerequisite for starting Portato was not matched." msgstr "Eine Vorbedingung um Portato zu starten ist nicht erfüllt." -#: portato/gui/dialogs.py:115 +#: portato/gui/dialogs.py:122 msgid "" "Note: On fresh Sabayon installs or its LiveDVD/-CD, there is no portage tree existing per default.\n" "Please run emerge --sync && layman -S." @@ -504,7 +518,7 @@ msgstr "" "Hinweis: Auf frisch installierten Sabayon-Systemen bzw. der Sabayon LiveDVD/-CD existiert standardmäßig kein Portage-Tree.\n" "Bitte führe emerge --sync && layman -S aus." -#: portato/gui/dialogs.py:123 +#: portato/gui/dialogs.py:130 #: portato/gui/windows/main.py:1302 #, python-format msgid "No versions of package '%s' found!" @@ -588,12 +602,12 @@ msgstr "Pakete mit Updates" msgid "World Packages" msgstr "Pakete in \"World\"" -#: portato/gui/windows/mailinfo.py:144 +#: portato/gui/windows/mailinfo.py:145 #, python-format msgid "An error occurred while sending. I think we were greylisted. The error: %s" msgstr "Während des Sendes trat ein Fehler auf. Wahrscheinlich wurden wir ge-greylistet. Der Fehler: %s" -#: portato/gui/windows/mailinfo.py:145 +#: portato/gui/windows/mailinfo.py:146 #, python-format msgid "Retrying after waiting %d seconds." msgstr "Wiederhole den Versuch nach einer %ds Pause." diff --git a/i18n/messages.pot b/i18n/messages.pot index 555837f..5c007f9 100644 --- a/i18n/messages.pot +++ b/i18n/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-03-14 20:01+0100\n" +"POT-Creation-Date: 2010-03-14 21:03+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -405,82 +405,95 @@ msgid "The error was: %s" msgstr "" #: portato/gui/dialogs.py:24 -msgid "Do you really want to quit?" +msgid "No email address given" msgstr "" #: portato/gui/dialogs.py:25 msgid "" +"You haven't specified an email address. Without it, it will not be possible " +"for the developers to contact you for questions and thus it might be harder " +"to fix the bug.\n" +"\n" +"Do you want to proceed nevertheless?" +msgstr "" + +#: portato/gui/dialogs.py:31 +msgid "Do you really want to quit?" +msgstr "" + +#: portato/gui/dialogs.py:32 +msgid "" "There are some packages in the emerge queue and/or an emerge process is " "running." msgstr "" -#: portato/gui/dialogs.py:43 +#: portato/gui/dialogs.py:50 #, python-format msgid "%(blocked)s is blocked by %(blocks)s." msgstr "" -#: portato/gui/dialogs.py:44 +#: portato/gui/dialogs.py:51 msgid "Please unmerge the blocking package." msgstr "" -#: portato/gui/dialogs.py:50 +#: portato/gui/dialogs.py:57 msgid "You are not root." msgstr "" -#: portato/gui/dialogs.py:56 +#: portato/gui/dialogs.py:63 #, python-format msgid "%s seems to be masked." msgstr "" -#: portato/gui/dialogs.py:57 +#: portato/gui/dialogs.py:64 msgid "Do you want to unmask it and its dependencies?" msgstr "" -#: portato/gui/dialogs.py:63 +#: portato/gui/dialogs.py:70 msgid "Package not found!" msgstr "" -#: portato/gui/dialogs.py:69 +#: portato/gui/dialogs.py:76 msgid "Do not show this dialog again." msgstr "" -#: portato/gui/dialogs.py:70 +#: portato/gui/dialogs.py:77 #, python-format msgid "Changed %s" msgstr "" -#: portato/gui/dialogs.py:71 +#: portato/gui/dialogs.py:78 msgid "" "Portato will write these changes into the appropriate files.\n" "Please backup them if you think it is necessary." msgstr "" -#: portato/gui/dialogs.py:80 +#: portato/gui/dialogs.py:87 msgid "You cannot remove dependencies. :)" msgstr "" -#: portato/gui/dialogs.py:86 +#: portato/gui/dialogs.py:93 msgid "" "This is the updates queue. You cannot remove single elements.\n" "Do you want to clear the whole queue instead?" msgstr "" -#: portato/gui/dialogs.py:92 +#: portato/gui/dialogs.py:99 msgid "Do you really want to clear the whole queue?" msgstr "" -#: portato/gui/dialogs.py:111 +#: portato/gui/dialogs.py:118 msgid "A prerequisite for starting Portato was not matched." msgstr "" -#: portato/gui/dialogs.py:115 +#: portato/gui/dialogs.py:122 msgid "" "Note: On fresh Sabayon installs or its LiveDVD/-CD, there is no " "portage tree existing per default.\n" "Please run emerge --sync && layman -S." msgstr "" -#: portato/gui/dialogs.py:123 portato/gui/windows/main.py:1302 +#: portato/gui/dialogs.py:130 portato/gui/windows/main.py:1302 #, python-format msgid "No versions of package '%s' found!" msgstr "" @@ -568,13 +581,13 @@ msgstr "" msgid "World Packages" msgstr "" -#: portato/gui/windows/mailinfo.py:144 +#: portato/gui/windows/mailinfo.py:145 #, python-format msgid "" "An error occurred while sending. I think we were greylisted. The error: %s" msgstr "" -#: portato/gui/windows/mailinfo.py:145 +#: portato/gui/windows/mailinfo.py:146 #, python-format msgid "Retrying after waiting %d seconds." msgstr "" diff --git a/portato/gui/dialogs.py b/portato/gui/dialogs.py index 6044a5b..7ad5c7f 100644 --- a/portato/gui/dialogs.py +++ b/portato/gui/dialogs.py @@ -20,6 +20,13 @@ def mail_failure_dialog(e): dialog.destroy() return ret +def no_email_dialog(p): + dialog = gtk.MessageDialog(p, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK_CANCEL, _("No email address given")) + dialog.format_secondary_text(_("You haven't specified an email address. Without it, it will not be possible for the developers to contact you for questions and thus it might be harder to fix the bug.\n\nDo you want to proceed nevertheless?")) + ret = dialog.run() + dialog.destroy() + return ret + def queue_not_empty_dialog(): dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, _("Do you really want to quit?")) dialog.format_secondary_text(_("There are some packages in the emerge queue and/or an emerge process is running.")) diff --git a/portato/gui/windows/basic.py b/portato/gui/windows/basic.py index 92c35f4..01d31e5 100644 --- a/portato/gui/windows/basic.py +++ b/portato/gui/windows/basic.py @@ -151,6 +151,9 @@ class AbstractDialog (Window): self.window.set_transient_for(parent) self.parent = parent + # type hint + self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) + # catch the ESC-key self.window.connect("key-press-event", self.cb_key_pressed) diff --git a/portato/gui/windows/mailinfo.py b/portato/gui/windows/mailinfo.py index 6d6e93b..c5002e7 100644 --- a/portato/gui/windows/mailinfo.py +++ b/portato/gui/windows/mailinfo.py @@ -21,7 +21,7 @@ from os.path import basename from .basic import AbstractDialog from ..utils import GtkThread -from ..dialogs import mail_failure_dialog +from ..dialogs import mail_failure_dialog, no_email_dialog from ...helper import debug, info from ...constants import VERSION, CONFIG_LOCATION from ...log import LOGFILE @@ -61,6 +61,7 @@ class MailInfoWindow (AbstractDialog): self.fileList = self.tree.get_widget("fileList") self.build_file_list() + self.mailEntry = self.tree.get_widget("mailEntry") self.tb = tb self.window.show_all() @@ -99,7 +100,7 @@ class MailInfoWindow (AbstractDialog): # TO and FROM name = self.tree.get_widget("nameEntry").get_text() - self.addr = self.tree.get_widget("mailEntry").get_text() + self.addr = self.mailEntry.get_text() if not self.addr: self.addr = self.TO @@ -157,7 +158,12 @@ class MailInfoWindow (AbstractDialog): return True def cb_send_clicked (self, *args): - self.set_data() - GtkThread(target = self.send, name = "Mail Send Thread").start() - self.close() + if self.mailEntry.get_text() or no_email_dialog(self.window) == gtk.RESPONSE_OK: + self.set_data() + GtkThread(target = self.send, name = "Mail Send Thread").start() + self.close() + else: + self.window.present() + self.mailEntry.grab_focus() + return True -- cgit v1.2.3-70-g09d2 From 5a52259b1404727718f57d44b266820542b9f1e6 Mon Sep 17 00:00:00 2001 From: René 'Necoro' Neumann Date: Fri, 26 Mar 2010 22:37:12 +0100 Subject: Fixed mailinfo window --- i18n/de.po | 4 +-- portato/gui/windows/mailinfo.py | 58 +++++++++++++++++++++++++++-------------- 2 files changed, 40 insertions(+), 22 deletions(-) (limited to 'portato/gui/windows/mailinfo.py') diff --git a/i18n/de.po b/i18n/de.po index d60a707..9935870 100644 --- a/i18n/de.po +++ b/i18n/de.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: Portato\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2010-03-14 21:03+0100\n" -"PO-Revision-Date: 2010-03-14 21:04+0100\n" +"PO-Revision-Date: 2010-03-26 22:31+0100\n" "Last-Translator: René 'Necoro' Neumann \n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -418,7 +418,7 @@ msgstr "Log" #: portato/gui/dialogs.py:17 msgid "Mail could not be sent" -msgstr "Mail konnte nicht gesendet werden: %s" +msgstr "Mail konnte nicht gesendet werden" #: portato/gui/dialogs.py:18 #, python-format diff --git a/portato/gui/windows/mailinfo.py b/portato/gui/windows/mailinfo.py index c5002e7..4367482 100644 --- a/portato/gui/windows/mailinfo.py +++ b/portato/gui/windows/mailinfo.py @@ -14,19 +14,23 @@ from __future__ import absolute_import, with_statement import smtplib, socket import time -import gtk, pango +import gtk, pango, gobject from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from os.path import basename from .basic import AbstractDialog from ..utils import GtkThread -from ..dialogs import mail_failure_dialog, no_email_dialog +from .. import dialogs from ...helper import debug, info from ...constants import VERSION, CONFIG_LOCATION from ...log import LOGFILE from ... import session +def mail_failure_dialog(*a): + dialogs.mail_failure_dialog(*a) + return False + class ShowDialog (gtk.Dialog): def __init__(self, parent, f): @@ -51,7 +55,7 @@ class ShowDialog (gtk.Dialog): self.vbox.show_all() class MailInfoWindow (AbstractDialog): - TO = "bugs@portato.necoro.net" + TO = "bugs@necoro.eu" def __init__ (self, parent, tb): @@ -97,6 +101,7 @@ class MailInfoWindow (AbstractDialog): self.message = MIMEMultipart() self.message["Subject"] = "[Bug Report] Bug in Portato %s" % VERSION self.message["To"] = self.TO + self.message["X-Portato-Version"] = VERSION # TO and FROM name = self.tree.get_widget("nameEntry").get_text() @@ -134,31 +139,44 @@ class MailInfoWindow (AbstractDialog): def send (self): try: - debug("Connecting to server") - server = smtplib.SMTP("mail.necoro.eu") - debug("Sending mail") - try: - for i in range(5): # try 5 times at max - try: - server.sendmail(self.addr, self.TO, self.message.as_string()) - except smtplib.SMTPRecipientsRefused, e: + for i in range(5): # try 5 times at max + if i > 0: + info(_("Retrying after waiting %d seconds."), 300) + time.sleep(300) + try: + debug("Connecting to server") + server = smtplib.SMTP("mail.necoro.eu") + debug("Sending mail") + + if smtplib._have_ssl: server.starttls() + else: debug("TLS not supported in Python. Continuing without it.") + + server.sendmail(self.addr, self.TO, self.message.as_string()) + except smtplib.SMTPRecipientsRefused, e: + if e.recipients[self.TO][0] < 500: info(_("An error occurred while sending. I think we were greylisted. The error: %s") % e) - info(_("Retrying after waiting %d seconds."), 30) - time.sleep(30) - else: - debug("Sent") - break - finally: - server.quit() + else: raise + else: + debug("Sent") + break + finally: + try: + server.quit() + except smtplib.SMTPServerDisconnected: + pass # ignore this except socket.error, e: - mail_failure_dialog("%s (Code: %s)" % (e.args[1], e.args[0])) + gobject.idle_add(mail_failure_dialog, "%s (Code: %s)" % (e.args[1], e.args[0])) + except smtplib.SMTPResponseException, e: + gobject.idle_add(mail_failure_dialog, "%s (Code: %s)" % (e.smtp_error, e.smtp_code)) + except smtplib.SMTPException, e: + gobject.idle_add(mail_failure_dialog, e.args) def cb_cancel_clicked (self, *args): self.close() return True def cb_send_clicked (self, *args): - if self.mailEntry.get_text() or no_email_dialog(self.window) == gtk.RESPONSE_OK: + if self.mailEntry.get_text() or dialogs.no_email_dialog(self.window) == gtk.RESPONSE_OK: self.set_data() GtkThread(target = self.send, name = "Mail Send Thread").start() self.close() -- cgit v1.2.3-70-g09d2