62 # WORK AROUND: implement our corrected encoder |
62 # WORK AROUND: implement our corrected encoder |
63 |
63 |
64 |
64 |
65 class EmailDialog(QDialog, Ui_EmailDialog): |
65 class EmailDialog(QDialog, Ui_EmailDialog): |
66 """ |
66 """ |
67 Class implementing a dialog to send bug reports. |
67 Class implementing a dialog to send bug reports or feature requests. |
68 """ |
68 """ |
69 def __init__(self, mode="bug", parent=None): |
69 def __init__(self, mode="bug", parent=None): |
70 """ |
70 """ |
71 Constructor |
71 Constructor |
72 |
72 |
94 self.sendButton = self.buttonBox.addButton( |
94 self.sendButton = self.buttonBox.addButton( |
95 self.tr("Send"), QDialogButtonBox.ActionRole) |
95 self.tr("Send"), QDialogButtonBox.ActionRole) |
96 self.sendButton.setEnabled(False) |
96 self.sendButton.setEnabled(False) |
97 self.sendButton.setDefault(True) |
97 self.sendButton.setDefault(True) |
98 |
98 |
|
99 self.googleHelpButton = self.buttonBox.addButton( |
|
100 self.tr("Google Mail API Help"), QDialogButtonBox.HelpRole) |
|
101 |
99 height = self.height() |
102 height = self.height() |
100 self.mainSplitter.setSizes([int(0.7 * height), int(0.3 * height)]) |
103 self.mainSplitter.setSizes([int(0.7 * height), int(0.3 * height)]) |
101 |
104 |
102 self.attachments.headerItem().setText( |
105 self.attachments.headerItem().setText( |
103 self.attachments.columnCount(), "") |
106 self.attachments.columnCount(), "") |
115 self.message.setTextCursor(cursor) |
118 self.message.setTextCursor(cursor) |
116 self.message.ensureCursorVisible() |
119 self.message.ensureCursorVisible() |
117 |
120 |
118 self.__deleteFiles = [] |
121 self.__deleteFiles = [] |
119 |
122 |
|
123 self.__helpDialog = None |
|
124 |
120 def keyPressEvent(self, ev): |
125 def keyPressEvent(self, ev): |
121 """ |
126 """ |
122 Protected method to handle the user pressing the escape key. |
127 Protected method to handle the user pressing the escape key. |
123 |
128 |
124 @param ev key event (QKeyEvent) |
129 @param ev key event (QKeyEvent) |
137 |
142 |
138 @param button button that was clicked (QAbstractButton) |
143 @param button button that was clicked (QAbstractButton) |
139 """ |
144 """ |
140 if button == self.sendButton: |
145 if button == self.sendButton: |
141 self.on_sendButton_clicked() |
146 self.on_sendButton_clicked() |
|
147 elif button == self.googleHelpButton: |
|
148 self.on_googleHelpButton_clicked() |
142 |
149 |
143 def on_buttonBox_rejected(self): |
150 def on_buttonBox_rejected(self): |
144 """ |
151 """ |
145 Private slot to handle the rejected signal of the button box. |
152 Private slot to handle the rejected signal of the button box. |
146 """ |
153 """ |
148 self, |
155 self, |
149 self.tr("Close dialog"), |
156 self.tr("Close dialog"), |
150 self.tr("""Do you really want to close the dialog?""")) |
157 self.tr("""Do you really want to close the dialog?""")) |
151 if res: |
158 if res: |
152 self.reject() |
159 self.reject() |
153 |
160 |
|
161 @pyqtSlot() |
|
162 def on_googleHelpButton_clicked(self): |
|
163 """ |
|
164 Private slot to show some help text "how to turn on the Gmail API". |
|
165 """ |
|
166 if self.__helpDialog is None: |
|
167 try: |
|
168 from E5Network.E5GoogleMail import GoogleMailHelp |
|
169 help = GoogleMailHelp() |
|
170 except ImportError: |
|
171 help = self.tr( |
|
172 "<p>The Google Mail Client API is not installed." |
|
173 " Use <code>pip install --upgrade google-api-python-client" |
|
174 "</code> to install it.</p>") |
|
175 |
|
176 from E5Gui.E5SimpleHelpDialog import E5SimpleHelpDialog |
|
177 self.__helpDialog = E5SimpleHelpDialog( |
|
178 title=self.tr("Gmail API Help"), |
|
179 help=help, parent=self) |
|
180 |
|
181 self.__helpDialog.show() |
|
182 |
154 @pyqtSlot() |
183 @pyqtSlot() |
155 def on_sendButton_clicked(self): |
184 def on_sendButton_clicked(self): |
156 """ |
185 """ |
157 Private slot to send the email message. |
186 Private slot to send the email message. |
158 """ |
187 """ |
159 if self.attachments.topLevelItemCount(): |
188 if self.attachments.topLevelItemCount(): |
160 msg = self.__createMultipartMail() |
189 msg = self.__createMultipartMail() |
161 else: |
190 else: |
162 msg = self.__createSimpleMail() |
191 msg = self.__createSimpleMail() |
163 |
192 |
164 ok = self.__sendmail(msg) |
193 if Preferences.getUser("UseGoogleMailOAuth2"): |
|
194 ok = self.__sendmailGoogle(msg) |
|
195 else: |
|
196 ok = self.__sendmail(msg.as_string()) |
165 |
197 |
166 if ok: |
198 if ok: |
167 for f in self.__deleteFiles: |
199 for f in self.__deleteFiles: |
168 try: |
200 try: |
169 os.remove(f) |
201 os.remove(f) |
201 |
233 |
202 def __createSimpleMail(self): |
234 def __createSimpleMail(self): |
203 """ |
235 """ |
204 Private method to create a simple mail message. |
236 Private method to create a simple mail message. |
205 |
237 |
206 @return string containing the mail message |
238 @return prepared mail message |
|
239 @rtype email.mime.text.MIMEText |
207 """ |
240 """ |
208 msgtext = "{0}\r\n----\r\n{1}----\r\n{2}----\r\n{3}".format( |
241 msgtext = "{0}\r\n----\r\n{1}----\r\n{2}----\r\n{3}".format( |
209 self.message.toPlainText(), |
242 self.message.toPlainText(), |
210 Utilities.generateVersionInfo("\r\n"), |
243 Utilities.generateVersionInfo("\r\n"), |
211 Utilities.generatePluginsVersionInfo("\r\n"), |
244 Utilities.generatePluginsVersionInfo("\r\n"), |
215 msg['From'] = Preferences.getUser("Email") |
248 msg['From'] = Preferences.getUser("Email") |
216 msg['To'] = self.__toAddress |
249 msg['To'] = self.__toAddress |
217 subject = '[eric6] {0}'.format(self.subject.text()) |
250 subject = '[eric6] {0}'.format(self.subject.text()) |
218 msg['Subject'] = self.__encodedHeader(subject) |
251 msg['Subject'] = self.__encodedHeader(subject) |
219 |
252 |
220 return msg.as_string() |
253 return msg |
221 |
254 |
222 def __createMultipartMail(self): |
255 def __createMultipartMail(self): |
223 """ |
256 """ |
224 Private method to create a multipart mail message. |
257 Private method to create a multipart mail message. |
225 |
258 |
226 @return string containing the mail message |
259 @return prepared mail message |
|
260 @rtype email.mime.text.MIMEMultipart |
227 """ |
261 """ |
228 mpPreamble = ("This is a MIME-encoded message with attachments. " |
262 mpPreamble = ("This is a MIME-encoded message with attachments. " |
229 "If you see this message, your mail client is not " |
263 "If you see this message, your mail client is not " |
230 "capable of displaying the attachments.") |
264 "capable of displaying the attachments.") |
231 |
265 |
271 else: |
305 else: |
272 att = MIMEApplication(open(fname, 'rb').read()) |
306 att = MIMEApplication(open(fname, 'rb').read()) |
273 att.add_header('Content-Disposition', 'attachment', filename=name) |
307 att.add_header('Content-Disposition', 'attachment', filename=name) |
274 msg.attach(att) |
308 msg.attach(att) |
275 |
309 |
276 return msg.as_string() |
310 return msg |
277 |
311 |
278 def __sendmail(self, msg): |
312 def __sendmail(self, msg): |
279 """ |
313 """ |
280 Private method to actually send the message. |
314 Private method to actually send the message. |
281 |
315 |
346 errorStr = e.strerror |
380 errorStr = e.strerror |
347 else: |
381 else: |
348 errorStr = str(e) |
382 errorStr = str(e) |
349 res = E5MessageBox.retryAbort( |
383 res = E5MessageBox.retryAbort( |
350 self, |
384 self, |
351 self.tr("Send bug report"), |
385 self.tr("Send Message"), |
352 self.tr( |
386 self.tr( |
353 """<p>Message could not be sent.<br>Reason: {0}</p>""") |
387 """<p>Message could not be sent.<br>Reason: {0}</p>""") |
354 .format(errorStr), |
388 .format(errorStr), |
355 E5MessageBox.Critical) |
389 E5MessageBox.Critical) |
356 if res: |
390 if res: |
357 return self.__sendmail(msg) |
391 return self.__sendmail(msg) |
358 else: |
392 else: |
359 return False |
393 return False |
360 return True |
394 return True |
361 |
395 |
|
396 |
|
397 def __sendmailGoogle(self, msg): |
|
398 """ |
|
399 Private method to actually send the message via Google Mail. |
|
400 |
|
401 @param message email message to be sent |
|
402 @type email.mime.text.MIMEBase |
|
403 @return flag indicating success |
|
404 @rtype bool |
|
405 """ |
|
406 from E5Network.E5GoogleMail import GoogleMailSendMessage |
|
407 QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) |
|
408 QApplication.processEvents() |
|
409 ok, result = GoogleMailSendMessage(msg) |
|
410 QApplication.restoreOverrideCursor() |
|
411 if not ok: |
|
412 # we got an error |
|
413 E5MessageBox.critical( |
|
414 self, |
|
415 self.tr("Send Message"), |
|
416 self.tr( |
|
417 """<p>Message could not be sent.<br>Reason: {0}</p>""") |
|
418 .format(result) |
|
419 ) |
|
420 |
|
421 return ok |
|
422 |
362 @pyqtSlot() |
423 @pyqtSlot() |
363 def on_addButton_clicked(self): |
424 def on_addButton_clicked(self): |
364 """ |
425 """ |
365 Private slot to handle the Add... button. |
426 Private slot to handle the Add... button. |
366 """ |
427 """ |