##// END OF EJS Templates
Added limit option for revision ranges
marcink -
r984:ccd323bf beta
parent child Browse files
Show More
@@ -1,243 +1,247 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.changeset
3 rhodecode.controllers.changeset
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 changeset controller for pylons showoing changes beetween
6 changeset controller for pylons showoing changes beetween
7 revisions
7 revisions
8
8
9 :created_on: Apr 25, 2010
9 :created_on: Apr 25, 2010
10 :author: marcink
10 :author: marcink
11 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
12 :license: GPLv3, see COPYING for more details.
12 :license: GPLv3, see COPYING for more details.
13 """
13 """
14 # This program is free software; you can redistribute it and/or
14 # This program is free software; you can redistribute it and/or
15 # modify it under the terms of the GNU General Public License
15 # modify it under the terms of the GNU General Public License
16 # as published by the Free Software Foundation; version 2
16 # as published by the Free Software Foundation; version 2
17 # of the License or (at your opinion) any later version of the license.
17 # of the License or (at your opinion) any later version of the license.
18 #
18 #
19 # This program is distributed in the hope that it will be useful,
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
22 # GNU General Public License for more details.
23 #
23 #
24 # You should have received a copy of the GNU General Public License
24 # You should have received a copy of the GNU General Public License
25 # along with this program; if not, write to the Free Software
25 # along with this program; if not, write to the Free Software
26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 # MA 02110-1301, USA.
27 # MA 02110-1301, USA.
28 import logging
28 import logging
29 import traceback
29 import traceback
30
30
31 from pylons import tmpl_context as c, url, request, response
31 from pylons import tmpl_context as c, url, request, response
32 from pylons.i18n.translation import _
32 from pylons.i18n.translation import _
33 from pylons.controllers.util import redirect
33 from pylons.controllers.util import redirect
34
34
35 import rhodecode.lib.helpers as h
35 import rhodecode.lib.helpers as h
36 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
36 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
37 from rhodecode.lib.base import BaseController, render
37 from rhodecode.lib.base import BaseController, render
38 from rhodecode.lib.utils import EmptyChangeset
38 from rhodecode.lib.utils import EmptyChangeset
39 from rhodecode.model.scm import ScmModel
39 from rhodecode.model.scm import ScmModel
40
40
41 from vcs.exceptions import RepositoryError, ChangesetError, \
41 from vcs.exceptions import RepositoryError, ChangesetError, \
42 ChangesetDoesNotExistError
42 ChangesetDoesNotExistError
43 from vcs.nodes import FileNode
43 from vcs.nodes import FileNode
44 from vcs.utils import diffs as differ
44 from vcs.utils import diffs as differ
45 from vcs.utils.ordered_dict import OrderedDict
45 from vcs.utils.ordered_dict import OrderedDict
46
46
47 log = logging.getLogger(__name__)
47 log = logging.getLogger(__name__)
48
48
49 class ChangesetController(BaseController):
49 class ChangesetController(BaseController):
50
50
51 @LoginRequired()
51 @LoginRequired()
52 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
52 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
53 'repository.admin')
53 'repository.admin')
54 def __before__(self):
54 def __before__(self):
55 super(ChangesetController, self).__before__()
55 super(ChangesetController, self).__before__()
56
56
57 def index(self, revision):
57 def index(self, revision):
58 hg_model = ScmModel()
58 hg_model = ScmModel()
59
59
60 def wrap_to_table(str):
60 def wrap_to_table(str):
61
61
62 return '''<table class="code-difftable">
62 return '''<table class="code-difftable">
63 <tr class="line">
63 <tr class="line">
64 <td class="lineno new"></td>
64 <td class="lineno new"></td>
65 <td class="code"><pre>%s</pre></td>
65 <td class="code"><pre>%s</pre></td>
66 </tr>
66 </tr>
67 </table>''' % str
67 </table>''' % str
68
68
69 def get_cs_range(repo, rev_start, rev_end):
69 def get_cs_range(repo, rev_start, rev_end, limit=None):
70 """
70 """
71 Temp fix function until VCS will handle that
71 Temp fix function until VCS will handle that
72 see issue #48
72 see issue #48
73 :param rev_start:
73 :param rev_start:
74 :param rev_end:
74 :param rev_end:
75 """
75 """
76
76
77 start_cs = repo.get_changeset(rev_start)
77 start_cs = repo.get_changeset(rev_start)
78 end_cs = repo.get_changeset(rev_end)
78 end_cs = repo.get_changeset(rev_end)
79
79
80 if start_cs.revision >= end_cs.revision:
80 if start_cs.revision >= end_cs.revision:
81 raise Exception('Start revision cannot be after End')
81 raise Exception('Start revision cannot be after End')
82
82
83 yield start_cs
83 yield start_cs
84
84
85 cnt = 0
85 while 1:
86 while 1:
87
86 next = start_cs.next()
88 next = start_cs.next()
87 yield next
89 yield next
88 start_cs = next
90 start_cs = next
91 cnt += 1
89 if next == end_cs:
92 if next == end_cs:
90 break
93 break
91
94 if limit and cnt > limit:
95 break
92 #======================================================================
96 #======================================================================
93 # REAL CODE BELOW
97 # REAL CODE BELOW
94 #======================================================================
98 #======================================================================
95 #get ranges of revisions if preset
99 #get ranges of revisions if preset
96 rev_range = revision.split('...')[:2]
100 rev_range = revision.split('...')[:2]
97
101 range_limit = 50
98 try:
102 try:
99 repo = hg_model.get_repo(c.repo_name)
103 repo = hg_model.get_repo(c.repo_name)
100 if len(rev_range) == 2:
104 if len(rev_range) == 2:
101 rev_start = rev_range[0]
105 rev_start = rev_range[0]
102 rev_end = rev_range[1]
106 rev_end = rev_range[1]
103 rev_ranges = get_cs_range(repo, rev_start, rev_end)
107 rev_ranges = get_cs_range(repo, rev_start, rev_end, range_limit)
104 else:
108 else:
105 rev_ranges = [repo.get_changeset(revision)]
109 rev_ranges = [repo.get_changeset(revision)]
106
110
107 c.cs_ranges = list(rev_ranges)
111 c.cs_ranges = list(rev_ranges)
108
112
109 except (RepositoryError, ChangesetDoesNotExistError, Exception), e:
113 except (RepositoryError, ChangesetDoesNotExistError, Exception), e:
110 log.error(traceback.format_exc())
114 log.error(traceback.format_exc())
111 h.flash(str(e), category='warning')
115 h.flash(str(e), category='warning')
112 return redirect(url('home'))
116 return redirect(url('home'))
113
117
114 c.changes = OrderedDict()
118 c.changes = OrderedDict()
115 c.sum_added = 0
119 c.sum_added = 0
116 c.sum_removed = 0
120 c.sum_removed = 0
117
121
118
122
119 for changeset in c.cs_ranges:
123 for changeset in c.cs_ranges:
120 c.changes[changeset.raw_id] = []
124 c.changes[changeset.raw_id] = []
121 try:
125 try:
122 changeset_parent = changeset.parents[0]
126 changeset_parent = changeset.parents[0]
123 except IndexError:
127 except IndexError:
124 changeset_parent = None
128 changeset_parent = None
125
129
126
130
127 #==================================================================
131 #==================================================================
128 # ADDED FILES
132 # ADDED FILES
129 #==================================================================
133 #==================================================================
130 for node in changeset.added:
134 for node in changeset.added:
131 filenode_old = FileNode(node.path, '', EmptyChangeset())
135 filenode_old = FileNode(node.path, '', EmptyChangeset())
132 if filenode_old.is_binary or node.is_binary:
136 if filenode_old.is_binary or node.is_binary:
133 diff = wrap_to_table(_('binary file'))
137 diff = wrap_to_table(_('binary file'))
134 else:
138 else:
135 c.sum_added += node.size
139 c.sum_added += node.size
136 if c.sum_added < self.cut_off_limit:
140 if c.sum_added < self.cut_off_limit:
137 f_udiff = differ.get_udiff(filenode_old, node)
141 f_udiff = differ.get_udiff(filenode_old, node)
138 diff = differ.DiffProcessor(f_udiff).as_html()
142 diff = differ.DiffProcessor(f_udiff).as_html()
139
143
140 else:
144 else:
141 diff = wrap_to_table(_('Changeset is to big and was cut'
145 diff = wrap_to_table(_('Changeset is to big and was cut'
142 ' off, see raw changeset instead'))
146 ' off, see raw changeset instead'))
143
147
144 cs1 = None
148 cs1 = None
145 cs2 = node.last_changeset.raw_id
149 cs2 = node.last_changeset.raw_id
146 c.changes[changeset.raw_id].append(('added', node, diff, cs1, cs2))
150 c.changes[changeset.raw_id].append(('added', node, diff, cs1, cs2))
147
151
148 #==================================================================
152 #==================================================================
149 # CHANGED FILES
153 # CHANGED FILES
150 #==================================================================
154 #==================================================================
151 for node in changeset.changed:
155 for node in changeset.changed:
152 try:
156 try:
153 filenode_old = changeset_parent.get_node(node.path)
157 filenode_old = changeset_parent.get_node(node.path)
154 except ChangesetError:
158 except ChangesetError:
155 filenode_old = FileNode(node.path, '', EmptyChangeset())
159 filenode_old = FileNode(node.path, '', EmptyChangeset())
156
160
157 if filenode_old.is_binary or node.is_binary:
161 if filenode_old.is_binary or node.is_binary:
158 diff = wrap_to_table(_('binary file'))
162 diff = wrap_to_table(_('binary file'))
159 else:
163 else:
160
164
161 if c.sum_removed < self.cut_off_limit:
165 if c.sum_removed < self.cut_off_limit:
162 f_udiff = differ.get_udiff(filenode_old, node)
166 f_udiff = differ.get_udiff(filenode_old, node)
163 diff = differ.DiffProcessor(f_udiff).as_html()
167 diff = differ.DiffProcessor(f_udiff).as_html()
164 if diff:
168 if diff:
165 c.sum_removed += len(diff)
169 c.sum_removed += len(diff)
166 else:
170 else:
167 diff = wrap_to_table(_('Changeset is to big and was cut'
171 diff = wrap_to_table(_('Changeset is to big and was cut'
168 ' off, see raw changeset instead'))
172 ' off, see raw changeset instead'))
169
173
170
174
171 cs1 = filenode_old.last_changeset.raw_id
175 cs1 = filenode_old.last_changeset.raw_id
172 cs2 = node.last_changeset.raw_id
176 cs2 = node.last_changeset.raw_id
173 c.changes[changeset.raw_id].append(('changed', node, diff, cs1, cs2))
177 c.changes[changeset.raw_id].append(('changed', node, diff, cs1, cs2))
174
178
175 #==================================================================
179 #==================================================================
176 # REMOVED FILES
180 # REMOVED FILES
177 #==================================================================
181 #==================================================================
178 for node in changeset.removed:
182 for node in changeset.removed:
179 c.changes[changeset.raw_id].append(('removed', node, None, None, None))
183 c.changes[changeset.raw_id].append(('removed', node, None, None, None))
180
184
181 if len(c.cs_ranges) == 1:
185 if len(c.cs_ranges) == 1:
182 c.changeset = c.cs_ranges[0]
186 c.changeset = c.cs_ranges[0]
183 c.changes = c.changes[c.changeset.raw_id]
187 c.changes = c.changes[c.changeset.raw_id]
184
188
185 return render('changeset/changeset.html')
189 return render('changeset/changeset.html')
186 else:
190 else:
187 return render('changeset/changeset_range.html')
191 return render('changeset/changeset_range.html')
188
192
189 def raw_changeset(self, revision):
193 def raw_changeset(self, revision):
190
194
191 hg_model = ScmModel()
195 hg_model = ScmModel()
192 method = request.GET.get('diff', 'show')
196 method = request.GET.get('diff', 'show')
193 try:
197 try:
194 r = hg_model.get_repo(c.repo_name)
198 r = hg_model.get_repo(c.repo_name)
195 c.scm_type = r.alias
199 c.scm_type = r.alias
196 c.changeset = r.get_changeset(revision)
200 c.changeset = r.get_changeset(revision)
197 except RepositoryError:
201 except RepositoryError:
198 log.error(traceback.format_exc())
202 log.error(traceback.format_exc())
199 return redirect(url('home'))
203 return redirect(url('home'))
200 else:
204 else:
201 try:
205 try:
202 c.changeset_parent = c.changeset.parents[0]
206 c.changeset_parent = c.changeset.parents[0]
203 except IndexError:
207 except IndexError:
204 c.changeset_parent = None
208 c.changeset_parent = None
205 c.changes = []
209 c.changes = []
206
210
207 for node in c.changeset.added:
211 for node in c.changeset.added:
208 filenode_old = FileNode(node.path, '')
212 filenode_old = FileNode(node.path, '')
209 if filenode_old.is_binary or node.is_binary:
213 if filenode_old.is_binary or node.is_binary:
210 diff = _('binary file') + '\n'
214 diff = _('binary file') + '\n'
211 else:
215 else:
212 f_udiff = differ.get_udiff(filenode_old, node)
216 f_udiff = differ.get_udiff(filenode_old, node)
213 diff = differ.DiffProcessor(f_udiff).raw_diff()
217 diff = differ.DiffProcessor(f_udiff).raw_diff()
214
218
215 cs1 = None
219 cs1 = None
216 cs2 = node.last_changeset.raw_id
220 cs2 = node.last_changeset.raw_id
217 c.changes.append(('added', node, diff, cs1, cs2))
221 c.changes.append(('added', node, diff, cs1, cs2))
218
222
219 for node in c.changeset.changed:
223 for node in c.changeset.changed:
220 filenode_old = c.changeset_parent.get_node(node.path)
224 filenode_old = c.changeset_parent.get_node(node.path)
221 if filenode_old.is_binary or node.is_binary:
225 if filenode_old.is_binary or node.is_binary:
222 diff = _('binary file')
226 diff = _('binary file')
223 else:
227 else:
224 f_udiff = differ.get_udiff(filenode_old, node)
228 f_udiff = differ.get_udiff(filenode_old, node)
225 diff = differ.DiffProcessor(f_udiff).raw_diff()
229 diff = differ.DiffProcessor(f_udiff).raw_diff()
226
230
227 cs1 = filenode_old.last_changeset.raw_id
231 cs1 = filenode_old.last_changeset.raw_id
228 cs2 = node.last_changeset.raw_id
232 cs2 = node.last_changeset.raw_id
229 c.changes.append(('changed', node, diff, cs1, cs2))
233 c.changes.append(('changed', node, diff, cs1, cs2))
230
234
231 response.content_type = 'text/plain'
235 response.content_type = 'text/plain'
232
236
233 if method == 'download':
237 if method == 'download':
234 response.content_disposition = 'attachment; filename=%s.patch' % revision
238 response.content_disposition = 'attachment; filename=%s.patch' % revision
235
239
236 parent = True if len(c.changeset.parents) > 0 else False
240 parent = True if len(c.changeset.parents) > 0 else False
237 c.parent_tmpl = 'Parent %s' % c.changeset.parents[0].raw_id if parent else ''
241 c.parent_tmpl = 'Parent %s' % c.changeset.parents[0].raw_id if parent else ''
238
242
239 c.diffs = ''
243 c.diffs = ''
240 for x in c.changes:
244 for x in c.changes:
241 c.diffs += x[2]
245 c.diffs += x[2]
242
246
243 return render('changeset/raw_changeset.html')
247 return render('changeset/raw_changeset.html')
@@ -1,143 +1,143 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.smtp_mailer
3 rhodecode.lib.smtp_mailer
4 ~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Simple smtp mailer used in RhodeCode
6 Simple smtp mailer used in RhodeCode
7
7
8 :created_on: Sep 13, 2011
8 :created_on: Sep 13, 2010
9 :copyright: (c) 2011 by marcink.
9 :copyright: (c) 2011 by marcink.
10 :license: LICENSE_NAME, see LICENSE_FILE for more details.
10 :license: LICENSE_NAME, see LICENSE_FILE for more details.
11 """
11 """
12
12
13 import logging
13 import logging
14 import smtplib
14 import smtplib
15 import mimetypes
15 import mimetypes
16 from socket import sslerror
16 from socket import sslerror
17
17
18 from email.mime.multipart import MIMEMultipart
18 from email.mime.multipart import MIMEMultipart
19 from email.mime.image import MIMEImage
19 from email.mime.image import MIMEImage
20 from email.mime.audio import MIMEAudio
20 from email.mime.audio import MIMEAudio
21 from email.mime.base import MIMEBase
21 from email.mime.base import MIMEBase
22 from email.mime.text import MIMEText
22 from email.mime.text import MIMEText
23 from email.utils import formatdate
23 from email.utils import formatdate
24 from email import encoders
24 from email import encoders
25
25
26 class SmtpMailer(object):
26 class SmtpMailer(object):
27 """SMTP mailer class
27 """SMTP mailer class
28
28
29 mailer = SmtpMailer(mail_from, user, passwd, mail_server, mail_port, ssl, tls)
29 mailer = SmtpMailer(mail_from, user, passwd, mail_server, mail_port, ssl, tls)
30 mailer.send(recipients, subject, body, attachment_files)
30 mailer.send(recipients, subject, body, attachment_files)
31
31
32 :param recipients might be a list of string or single string
32 :param recipients might be a list of string or single string
33 :param attachment_files is a dict of {filename:location}
33 :param attachment_files is a dict of {filename:location}
34 it tries to guess the mimetype and attach the file
34 it tries to guess the mimetype and attach the file
35
35
36 """
36 """
37
37
38 def __init__(self, mail_from, user, passwd, mail_server,
38 def __init__(self, mail_from, user, passwd, mail_server,
39 mail_port=None, ssl=False, tls=False):
39 mail_port=None, ssl=False, tls=False):
40
40
41 self.mail_from = mail_from
41 self.mail_from = mail_from
42 self.mail_server = mail_server
42 self.mail_server = mail_server
43 self.mail_port = mail_port
43 self.mail_port = mail_port
44 self.user = user
44 self.user = user
45 self.passwd = passwd
45 self.passwd = passwd
46 self.ssl = ssl
46 self.ssl = ssl
47 self.tls = tls
47 self.tls = tls
48 self.debug = False
48 self.debug = False
49
49
50 def send(self, recipients=[], subject='', body='', attachment_files={}):
50 def send(self, recipients=[], subject='', body='', attachment_files={}):
51
51
52 if isinstance(recipients, basestring):
52 if isinstance(recipients, basestring):
53 recipients = [recipients]
53 recipients = [recipients]
54 if self.ssl:
54 if self.ssl:
55 smtp_serv = smtplib.SMTP_SSL(self.mail_server, self.mail_port)
55 smtp_serv = smtplib.SMTP_SSL(self.mail_server, self.mail_port)
56 else:
56 else:
57 smtp_serv = smtplib.SMTP(self.mail_server, self.mail_port)
57 smtp_serv = smtplib.SMTP(self.mail_server, self.mail_port)
58
58
59 if self.tls:
59 if self.tls:
60 smtp_serv.ehlo()
60 smtp_serv.ehlo()
61 smtp_serv.starttls()
61 smtp_serv.starttls()
62
62
63 if self.debug:
63 if self.debug:
64 smtp_serv.set_debuglevel(1)
64 smtp_serv.set_debuglevel(1)
65
65
66 smtp_serv.ehlo()
66 smtp_serv.ehlo()
67
67
68 #if server requires authorization you must provide login and password
68 #if server requires authorization you must provide login and password
69 #but only if we have them
69 #but only if we have them
70 if self.user and self.passwd:
70 if self.user and self.passwd:
71 smtp_serv.login(self.user, self.passwd)
71 smtp_serv.login(self.user, self.passwd)
72
72
73
73
74 date_ = formatdate(localtime=True)
74 date_ = formatdate(localtime=True)
75 msg = MIMEMultipart()
75 msg = MIMEMultipart()
76 msg['From'] = self.mail_from
76 msg['From'] = self.mail_from
77 msg['To'] = ','.join(recipients)
77 msg['To'] = ','.join(recipients)
78 msg['Date'] = date_
78 msg['Date'] = date_
79 msg['Subject'] = subject
79 msg['Subject'] = subject
80 msg.preamble = 'You will not see this in a MIME-aware mail reader.\n'
80 msg.preamble = 'You will not see this in a MIME-aware mail reader.\n'
81
81
82 msg.attach(MIMEText(body))
82 msg.attach(MIMEText(body))
83
83
84 if attachment_files:
84 if attachment_files:
85 self.__atach_files(msg, attachment_files)
85 self.__atach_files(msg, attachment_files)
86
86
87 smtp_serv.sendmail(self.mail_from, recipients, msg.as_string())
87 smtp_serv.sendmail(self.mail_from, recipients, msg.as_string())
88 logging.info('MAIL SEND TO: %s' % recipients)
88 logging.info('MAIL SEND TO: %s' % recipients)
89
89
90 try:
90 try:
91 smtp_serv.quit()
91 smtp_serv.quit()
92 except sslerror:
92 except sslerror:
93 # sslerror is raised in tls connections on closing sometimes
93 # sslerror is raised in tls connections on closing sometimes
94 pass
94 pass
95
95
96
96
97
97
98 def __atach_files(self, msg, attachment_files):
98 def __atach_files(self, msg, attachment_files):
99 if isinstance(attachment_files, dict):
99 if isinstance(attachment_files, dict):
100 for f_name, msg_file in attachment_files.items():
100 for f_name, msg_file in attachment_files.items():
101 ctype, encoding = mimetypes.guess_type(f_name)
101 ctype, encoding = mimetypes.guess_type(f_name)
102 logging.info("guessing file %s type based on %s" , ctype, f_name)
102 logging.info("guessing file %s type based on %s" , ctype, f_name)
103 if ctype is None or encoding is not None:
103 if ctype is None or encoding is not None:
104 # No guess could be made, or the file is encoded (compressed), so
104 # No guess could be made, or the file is encoded (compressed), so
105 # use a generic bag-of-bits type.
105 # use a generic bag-of-bits type.
106 ctype = 'application/octet-stream'
106 ctype = 'application/octet-stream'
107 maintype, subtype = ctype.split('/', 1)
107 maintype, subtype = ctype.split('/', 1)
108 if maintype == 'text':
108 if maintype == 'text':
109 # Note: we should handle calculating the charset
109 # Note: we should handle calculating the charset
110 file_part = MIMEText(self.get_content(msg_file),
110 file_part = MIMEText(self.get_content(msg_file),
111 _subtype=subtype)
111 _subtype=subtype)
112 elif maintype == 'image':
112 elif maintype == 'image':
113 file_part = MIMEImage(self.get_content(msg_file),
113 file_part = MIMEImage(self.get_content(msg_file),
114 _subtype=subtype)
114 _subtype=subtype)
115 elif maintype == 'audio':
115 elif maintype == 'audio':
116 file_part = MIMEAudio(self.get_content(msg_file),
116 file_part = MIMEAudio(self.get_content(msg_file),
117 _subtype=subtype)
117 _subtype=subtype)
118 else:
118 else:
119 file_part = MIMEBase(maintype, subtype)
119 file_part = MIMEBase(maintype, subtype)
120 file_part.set_payload(self.get_content(msg_file))
120 file_part.set_payload(self.get_content(msg_file))
121 # Encode the payload using Base64
121 # Encode the payload using Base64
122 encoders.encode_base64(msg)
122 encoders.encode_base64(msg)
123 # Set the filename parameter
123 # Set the filename parameter
124 file_part.add_header('Content-Disposition', 'attachment',
124 file_part.add_header('Content-Disposition', 'attachment',
125 filename=f_name)
125 filename=f_name)
126 file_part.add_header('Content-Type', ctype, name=f_name)
126 file_part.add_header('Content-Type', ctype, name=f_name)
127 msg.attach(file_part)
127 msg.attach(file_part)
128 else:
128 else:
129 raise Exception('Attachment files should be'
129 raise Exception('Attachment files should be'
130 'a dict in format {"filename":"filepath"}')
130 'a dict in format {"filename":"filepath"}')
131
131
132 def get_content(self, msg_file):
132 def get_content(self, msg_file):
133 '''
133 '''
134 Get content based on type, if content is a string do open first
134 Get content based on type, if content is a string do open first
135 else just read because it's a probably open file object
135 else just read because it's a probably open file object
136 :param msg_file:
136 :param msg_file:
137 '''
137 '''
138 if isinstance(msg_file, str):
138 if isinstance(msg_file, str):
139 return open(msg_file, "rb").read()
139 return open(msg_file, "rb").read()
140 else:
140 else:
141 #just for safe seek to 0
141 #just for safe seek to 0
142 msg_file.seek(0)
142 msg_file.seek(0)
143 return msg_file.read()
143 return msg_file.read()
General Comments 0
You need to be logged in to leave comments. Login now