[PATCH] Change in core[libreoffice-4-0]: make emailmerge work with python3 and python2 at the same ti...

Caolán McNamara (via_Code_Review) gerrit at gerrit.libreoffice.org
Wed Jan 16 04:39:59 PST 2013


Hi,

I have submitted a patch for review:

    https://gerrit.libreoffice.org/1713

To pull it, you can do:

    git pull ssh://gerrit.libreoffice.org:29418/core refs/changes/13/1713/1

make emailmerge work with python3 and python2 at the same time

squashed single 4-0 backport commit to sync 4-0 mailmerge.py
with that of current master to get a mailmerge.py that works
with python3 and python2, and successfully

a) sends utf-8 plain text
b) html
c) odt, pdf, doc attachments

(cherry picked from commit c25bee9ca3c3015c46c8fcb28654e5bed8a4d912)

i118736 - i118787 : fix XMailMessage implementation in mailmerge.py

(cherry picked from commit 4166969f3b8ed05e91c10a724ce7bd39074012a1)

(cherry picked from commit 3f2f92b753474883b5cd97aff3e00ac55fd23f3f)

i118791 - Encode ReadableName in UTF-8 only when necessary

(cherry picked from commit a5cefd4007be4789f550ee559aa832ddb04c2dc3)

i118814 - Allow set connection timeout in Mail API

(cherry picked from commit 8a324a3ba599bee03311e5f6ba6e1c83edc1e343)

make emailmerge work for me with python3

(cherry picked from commit e48a060eb80b76c943e7dbd815b63429905a14b6)

Change-Id: I6289b522513a2fc86e261c85a04ca9c89fd55b63
---
A scripting/source/pyprov/mailmerge.README
M scripting/source/pyprov/mailmerge.py
2 files changed, 110 insertions(+), 62 deletions(-)



diff --git a/scripting/source/pyprov/mailmerge.README b/scripting/source/pyprov/mailmerge.README
new file mode 100644
index 0000000..6b4fb5b
--- /dev/null
+++ b/scripting/source/pyprov/mailmerge.README
@@ -0,0 +1,18 @@
+Easiest way I find to test this is to...
+
+1)
+
+a) install fakemail and run it
+b) tools->options->writer->mail merge email
+c) localhost 8025
+
+2)
+
+a) type some text into writer that will exercise utf-8, e.g. "Caolán's test"
+b) tools->mail merge wizard->next->email message->select address book
+c) create, add one user with your own email address, ok
+d) next, next, text, send merged document as email
+e) and test all of plain text, html and the various attachment options
+
+fake mail will dump the mail it gets into its pwd, if all that works, you can
+then try with your own normal mail server.
diff --git a/scripting/source/pyprov/mailmerge.py b/scripting/source/pyprov/mailmerge.py
index c606143..18b476c 100755
--- a/scripting/source/pyprov/mailmerge.py
+++ b/scripting/source/pyprov/mailmerge.py
@@ -11,6 +11,8 @@
 #   <value>true</value>
 #  </prop>
 
+from __future__ import print_function
+
 import unohelper
 import uno
 import re
@@ -36,11 +38,14 @@
 
 from email.mime.base import MIMEBase
 from email.message import Message
+from email.charset import Charset
+from email.charset import QP
 from email.encoders import encode_base64
 from email.header import Header
 from email.mime.multipart import MIMEMultipart
 from email.utils import formatdate
 from email.utils import parseaddr
+from socket import _GLOBAL_DEFAULT_TIMEOUT
 
 import sys, smtplib, imaplib, poplib
 dbg = False
@@ -59,42 +64,51 @@
 		self.supportedtypes = ('Insecure', 'Ssl')
 		self.server = None
 		self.connectioncontext = None
-		self.notify = EventObject()
+		self.notify = EventObject(self)
 		if dbg:
-			print("PyMailSMPTService init", file=dbgout)
+			print("PyMailSMTPService init", file=dbgout)
 	def addConnectionListener(self, xListener):
 		if dbg:
-			print("PyMailSMPTService addConnectionListener", file=dbgout)
+			print("PyMailSMTPService addConnectionListener", file=dbgout)
 		self.listeners.append(xListener)
 	def removeConnectionListener(self, xListener):
 		if dbg:
-			print("PyMailSMPTService removeConnectionListener", file=dbgout)
+			print("PyMailSMTPService removeConnectionListener", file=dbgout)
 		self.listeners.remove(xListener)
 	def getSupportedConnectionTypes(self):
 		if dbg:
-			print("PyMailSMPTService getSupportedConnectionTypes", file=dbgout)
+			print("PyMailSMTPService getSupportedConnectionTypes", file=dbgout)
 		return self.supportedtypes
 	def connect(self, xConnectionContext, xAuthenticator):
 		self.connectioncontext = xConnectionContext
 		if dbg:
-			print("PyMailSMPTService connect", file=dbgout)
+			print("PyMailSMTPService connect", file=dbgout)
 		server = xConnectionContext.getValueByName("ServerName")
 		if dbg:
-			print(server, file=dbgout)
+			print("ServerName: " + server, file=dbgout)
 		port = int(xConnectionContext.getValueByName("Port"))
 		if dbg:
-			print(port, file=dbgout)
-		self.server = smtplib.SMTP(server, port)
+			print("Port: " + str(port), file=dbgout)
+		tout = xConnectionContext.getValueByName("Timeout")
+		if dbg:
+			print(isinstance(tout,int), file=dbgout)
+		if not isinstance(tout,int):
+			tout = _GLOBAL_DEFAULT_TIMEOUT
+		if dbg:
+			print("Timeout: " + str(tout), file=dbgout)
+		self.server = smtplib.SMTP(server, port,timeout=tout)
+
 		#stderr not available for us under windows, but
 		#set_debuglevel outputs there, and so throw
 		#an exception under windows on debugging mode
 		#with this enabled
 		if dbg and os.name != 'nt':
 			self.server.set_debuglevel(1)
+
 		connectiontype = xConnectionContext.getValueByName("ConnectionType")
 		if dbg:
-			print(connectiontype, file=dbgout)
-		if connectiontype == 'Ssl':
+			print("ConnectionType: " + connectiontype, file=dbgout)
+		if connectiontype.upper() == 'SSL':
 			self.server.ehlo()
 			self.server.starttls()
 			self.server.ehlo()
@@ -106,14 +120,14 @@
 				user = user.encode('ascii')
 				password = password.encode('ascii')
 			if dbg:
-				print("Logging in, username of" + user, file=dbgout)
+				print("Logging in, username of: " + user, file=dbgout)
 			self.server.login(user, password)
 
 		for listener in self.listeners:
 			listener.connected(self.notify)
 	def disconnect(self):
 		if dbg:
-			print("PyMailSMPTService disconnect", file=dbgout)
+			print("PyMailSMTPService disconnect", file=dbgout)
 		if self.server:
 			self.server.quit()
 			self.server = None
@@ -121,17 +135,17 @@
 			listener.disconnected(self.notify)
 	def isConnected(self):
 		if dbg:
-			print("PyMailSMPTService isConnected", file=dbgout)
+			print("PyMailSMTPService isConnected", file=dbgout)
 		return self.server != None
 	def getCurrentConnectionContext(self):
 		if dbg:
-			print("PyMailSMPTService getCurrentConnectionContext", file=dbgout)
+			print("PyMailSMTPService getCurrentConnectionContext", file=dbgout)
 		return self.connectioncontext
 	def sendMailMessage(self, xMailMessage):
 		COMMASPACE = ', '
 
 		if dbg:
-			print("PyMailSMPTService sendMailMessage", file=dbgout)
+			print("PyMailSMTPService sendMailMessage", file=dbgout)
 		recipients = xMailMessage.getRecipients()
 		sendermail = xMailMessage.SenderAddress
 		sendername = xMailMessage.SenderName
@@ -139,10 +153,10 @@
 		ccrecipients = xMailMessage.getCcRecipients()
 		bccrecipients = xMailMessage.getBccRecipients()
 		if dbg:
-			print("PyMailSMPTService subject " + subject, file=dbgout)
-			print("PyMailSMPTService from " + sendername.encode('utf-8'), file=dbgout)
-			print("PyMailSMTPService from " + sendermail, file=dbgout)
-			print("PyMailSMPTService send to " + recipients, file=dbgout)
+			print("PyMailSMTPService subject: " + subject, file=dbgout)
+			print("PyMailSMTPService from:  " + sendername, file=dbgout)
+			print("PyMailSMTPService from:  " + sendermail, file=dbgout)
+			print("PyMailSMTPService send to: %s" % (recipients,), file=dbgout)
 
 		attachments = xMailMessage.getAttachments()
 
@@ -151,19 +165,14 @@
 		content = xMailMessage.Body
 		flavors = content.getTransferDataFlavors()
 		if dbg:
-			print("PyMailSMPTService flavors len " + len(flavors), file=dbgout)
+			print("PyMailSMTPService flavors len: %d" % (len(flavors),), file=dbgout)
 
 		#Use first flavor that's sane for an email body
 		for flavor in flavors:
 			if flavor.MimeType.find('text/html') != -1 or flavor.MimeType.find('text/plain') != -1:
 				if dbg:
-					print("PyMailSMPTService mimetype is " + flavor.MimeType, file=dbgout)
+					print("PyMailSMTPService mimetype is: " + flavor.MimeType, file=dbgout)
 				textbody = content.getTransferData(flavor)
-				try:
-					textbody = textbody.value
-				except:
-					pass
-				textbody = textbody.encode('utf-8')
 
 				if len(textbody):
 					mimeEncoding = re.sub("charset=.*", "charset=UTF-8", flavor.MimeType)
@@ -171,7 +180,16 @@
 						mimeEncoding = mimeEncoding + "; charset=UTF-8"
 					textmsg['Content-Type'] = mimeEncoding
 					textmsg['MIME-Version'] = '1.0'
-					textmsg.set_payload(textbody)
+
+					textbody = textbody.encode('utf-8')
+					if sys.version >= '3':
+						#http://stackoverflow.com/questions/9403265/how-do-i-use-python-3-2-email-module-to-send-unicode-messages-encoded-in-utf-8-w
+						textbody = textbody.decode('iso8859-1')
+						c = Charset('utf-8')
+						c.body_encoding = QP
+						textmsg.set_payload(textbody, c)
+					else:
+						textmsg.set_payload(textbody)
 
 				break
 
@@ -194,7 +212,7 @@
 
 		mailerstring = "LibreOffice via Caolan's mailmerge component"
 		try:
-			ctx = uno.getComponentContext() 
+			ctx = uno.getComponentContext()
 			aConfigProvider = ctx.ServiceManager.createInstance("com.sun.star.configuration.ConfigurationProvider")
 			prop = uno.createUnoStruct('com.sun.star.beans.PropertyValue')
 			prop.Name = "nodepath"
@@ -205,7 +223,7 @@
 				aSettings.getByName("ooSetupVersion") + " via Caolan's mailmerge component"
 		except:
 			pass
-		
+
 		msg['X-Mailer'] = mailerstring
 		msg['Date'] = formatdate(localtime=True)
 
@@ -217,10 +235,15 @@
 			maintype, subtype = ctype.split('/', 1)
 			msgattachment = MIMEBase(maintype, subtype)
 			data = content.getTransferData(flavor)
-			msgattachment.set_payload(data)
+			msgattachment.set_payload(data.value)
 			encode_base64(msgattachment)
+			fname = attachment.ReadableName
+			try:
+				fname.encode('ascii')
+			except:
+				fname = ('utf-8','',fname.encode('utf-8'))
 			msgattachment.add_header('Content-Disposition', 'attachment', \
-				filename=attachment.ReadableName)
+				filename=fname)
 			msg.attach(msgattachment)
 
 		uniquer = {}
@@ -235,7 +258,7 @@
 		truerecipients = uniquer.keys()
 
 		if dbg:
-			print("PyMailSMPTService recipients are " + truerecipients, file=dbgout)
+			print(("PyMailSMTPService recipients are: ", truerecipients), file=dbgout)
 
 		self.server.sendmail(sendermail, truerecipients, msg.as_string())
 
@@ -246,7 +269,7 @@
 		self.supportedtypes = ('Insecure', 'Ssl')
 		self.server = None
 		self.connectioncontext = None
-		self.notify = EventObject()
+		self.notify = EventObject(self)
 		if dbg:
 			print("PyMailIMAPService init", file=dbgout)
 	def addConnectionListener(self, xListener):
@@ -276,12 +299,12 @@
 		if dbg:
 			print(connectiontype, file=dbgout)
 		print("BEFORE", file=dbgout)
-		if connectiontype == 'Ssl':
+		if connectiontype.upper() == 'SSL':
 			self.server = imaplib.IMAP4_SSL(server, port)
 		else:
 			self.server = imaplib.IMAP4(server, port)
 		print("AFTER", file=dbgout)
-			
+
 		user = xAuthenticator.getUserName()
 		password = xAuthenticator.getPassword()
 		if user != '':
@@ -289,7 +312,7 @@
 				user = user.encode('ascii')
 				password = password.encode('ascii')
 			if dbg:
-				print("Logging in, username of" + user, file=dbgout)
+				print("Logging in, username of: " + user, file=dbgout)
 			self.server.login(user, password)
 
 		for listener in self.listeners:
@@ -318,7 +341,7 @@
 		self.supportedtypes = ('Insecure', 'Ssl')
 		self.server = None
 		self.connectioncontext = None
-		self.notify = EventObject()
+		self.notify = EventObject(self)
 		if dbg:
 			print("PyMailPOP3Service init", file=dbgout)
 	def addConnectionListener(self, xListener):
@@ -348,10 +371,17 @@
 		if dbg:
 			print(connectiontype, file=dbgout)
 		print("BEFORE", file=dbgout)
-		if connectiontype == 'Ssl':
+		if connectiontype.upper() == 'SSL':
 			self.server = poplib.POP3_SSL(server, port)
 		else:
-			self.server = poplib.POP3(server, port)
+			tout = xConnectionContext.getValueByName("Timeout")
+			if dbg:
+				print(isinstance(tout,int), file=dbgout)
+			if not isinstance(tout,int):
+				tout = _GLOBAL_DEFAULT_TIMEOUT
+			if dbg:
+				print("Timeout: " + str(tout), file=dbgout)
+			self.server = poplib.POP3(server, port, timeout=tout)
 		print("AFTER", file=dbgout)
 			
 		user = xAuthenticator.getUserName()
@@ -360,9 +390,9 @@
 			user = user.encode('ascii')
 			password = password.encode('ascii')
 		if dbg:
-			print("Logging in, username of" + user, file=dbgout)
+			print("Logging in, username of: " + user, file=dbgout)
 		self.server.user(user)
-		self.server.pass_(user, password)
+		self.server.pass_(password)
 
 		for listener in self.listeners:
 			listener.connected(self.notify)
@@ -390,7 +420,7 @@
 		self.ctx = ctx
 	def create(self, aType):
 		if dbg:
-			print("PyMailServiceProvider create with " + aType, file=dbgout)
+			print("PyMailServiceProvider create with", aType, file=dbgout)
 		if aType == SMTP:
 			return PyMailSMTPService(self.ctx);
 		elif aType == POP3:
@@ -406,12 +436,12 @@
 			print("PyMailMessage init", file=dbgout)
 		self.ctx = ctx
 
-		self.recipients = (sTo,)
-		self.ccrecipients = ()
-		self.bccrecipients = ()
-		self.aMailAttachments = ()
+		self.recipients = [sTo]
+		self.ccrecipients = []
+		self.bccrecipients = []
+		self.aMailAttachments = []
 		if aMailAttachment != None:
-			self.aMailAttachments = (aMailAttachment,)
+			self.aMailAttachments.append(aMailAttachment)
 
 		self.SenderName, self.SenderAddress = parseaddr(sFrom)
 		self.ReplyToAddress = sFrom
@@ -421,36 +451,36 @@
 			print("post PyMailMessage init", file=dbgout)
 	def addRecipient( self, recipient ):
 		if dbg:
-			print("PyMailMessage.addRecipient " + recipient, file=dbgout)
-		self.recipients = self.recipients + (recipient,)
+			print("PyMailMessage.addRecipient: " + recipient, file=dbgout)
+		self.recipients.append(recipient)
 	def addCcRecipient( self, ccrecipient ):
 		if dbg:
-			print("PyMailMessage.addCcRecipient " + ccrecipient, file=dbgout)
-		self.ccrecipients = self.ccrecipients + (ccrecipient,)
+			print("PyMailMessage.addCcRecipient: " + ccrecipient, file=dbgout)
+		self.ccrecipients.append(ccrecipient)
 	def addBccRecipient( self, bccrecipient ):
 		if dbg:
-			print("PyMailMessage.addBccRecipient " + bccrecipient, file=dbgout)
-		self.bccrecipients = self.bccrecipients + (bccrecipient,)
+			print("PyMailMessage.addBccRecipient: " + bccrecipient, file=dbgout)
+		self.bccrecipients.append(bccrecipient)
 	def getRecipients( self ):
 		if dbg:
-			print("PyMailMessage.getRecipients " + self.recipients, file=dbgout)
-		return self.recipients
+			print("PyMailMessage.getRecipients: " + self.recipients, file=dbgout)
+		return tuple(self.recipients)
 	def getCcRecipients( self ):
 		if dbg:
-			print("PyMailMessage.getCcRecipients " + self.ccrecipients, file=dbgout)
-		return self.ccrecipients
+			print("PyMailMessage.getCcRecipients: " + self.ccrecipients, file=dbgout)
+		return tuple(self.ccrecipients)
 	def getBccRecipients( self ):
 		if dbg:
-			print("PyMailMessage.getBccRecipients " + self.bccrecipients, file=dbgout)
-		return self.bccrecipients
+			print("PyMailMessage.getBccRecipients: " + self.bccrecipients, file=dbgout)
+		return tuple(self.bccrecipients)
 	def addAttachment( self, aMailAttachment ):
 		if dbg:
 			print("PyMailMessage.addAttachment", file=dbgout)
-		self.aMailAttachments = self.aMailAttachments + (aMailAttachment,)
+		self.aMailAttachments.append(aMailAttachment)
 	def getAttachments( self ):
 		if dbg:
 			print("PyMailMessage.getAttachments", file=dbgout)
-		return self.aMailAttachments
+		return tuple(self.aMailAttachments)
 
 # pythonloader looks for a static g_ImplementationHelper variable
 g_ImplementationHelper = unohelper.ImplementationHelper()

-- 
To view, visit https://gerrit.libreoffice.org/1713
To unsubscribe, visit https://gerrit.libreoffice.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I6289b522513a2fc86e261c85a04ca9c89fd55b63
Gerrit-PatchSet: 1
Gerrit-Project: core
Gerrit-Branch: libreoffice-4-0
Gerrit-Owner: Caolán McNamara <caolanm at redhat.com>



More information about the LibreOffice mailing list