##// END OF EJS Templates
integrations: email, fix plural/singular case and no pushed branches case....
marcink -
r2421:3ca1f08e default
parent child Browse files
Show More
@@ -1,283 +1,292 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2012-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 from __future__ import unicode_literals
22 22 import deform
23 23 import logging
24 24 import colander
25 25
26 26 from mako.template import Template
27 27
28 28 from rhodecode import events
29 29 from rhodecode.translation import _
30 30 from rhodecode.lib.celerylib import run_task
31 31 from rhodecode.lib.celerylib import tasks
32 32 from rhodecode.integrations.types.base import IntegrationTypeBase
33 33
34 34
35 35 log = logging.getLogger(__name__)
36 36
37 37 repo_push_template_plaintext = Template('''
38 38 Commits:
39 39
40 40 % for commit in data['push']['commits']:
41 41 ${commit['url']} by ${commit['author']} at ${commit['date']}
42 42 ${commit['message']}
43 43 ----
44 44
45 45 % endfor
46 46 ''')
47 47
48 48 ## TODO (marcink): think about putting this into a file, or use base.mako email template
49 49
50 50 repo_push_template_html = Template('''
51 51 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
52 52 <html xmlns="http://www.w3.org/1999/xhtml">
53 53 <head>
54 54 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
55 55 <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
56 56 <title>${subject}</title>
57 57 <style type="text/css">
58 58 /* Based on The MailChimp Reset INLINE: Yes. */
59 59 #outlook a {padding:0;} /* Force Outlook to provide a "view in browser" menu link. */
60 60 body{width:100% !important; -webkit-text-size-adjust:100%; -ms-text-size-adjust:100%; margin:0; padding:0;}
61 61 /* Prevent Webkit and Windows Mobile platforms from changing default font sizes.*/
62 62 .ExternalClass {width:100%;} /* Force Hotmail to display emails at full width */
63 63 .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height: 100%;}
64 64 /* Forces Hotmail to display normal line spacing. More on that: http://www.emailonacid.com/forum/viewthread/43/ */
65 65 #backgroundTable {margin:0; padding:0; line-height: 100% !important;}
66 66 /* End reset */
67 67
68 68 /* defaults for images*/
69 69 img {outline:none; text-decoration:none; -ms-interpolation-mode: bicubic;}
70 70 a img {border:none;}
71 71 .image_fix {display:block;}
72 72
73 73 body {line-height:1.2em;}
74 74 p {margin: 0 0 20px;}
75 75 h1, h2, h3, h4, h5, h6 {color:#323232!important;}
76 76 a {color:#427cc9;text-decoration:none;outline:none;cursor:pointer;}
77 77 a:focus {outline:none;}
78 78 a:hover {color: #305b91;}
79 79 h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {color:#427cc9!important;text-decoration:none!important;}
80 80 h1 a:active, h2 a:active, h3 a:active, h4 a:active, h5 a:active, h6 a:active {color: #305b91!important;}
81 81 h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited {color: #305b91!important;}
82 82 table {font-size:13px;border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt;}
83 83 table td {padding:.65em 1em .65em 0;border-collapse:collapse;vertical-align:top;text-align:left;}
84 84 input {display:inline;border-radius:2px;border-style:solid;border: 1px solid #dbd9da;padding:.5em;}
85 85 input:focus {outline: 1px solid #979797}
86 86 @media only screen and (-webkit-min-device-pixel-ratio: 2) {
87 87 /* Put your iPhone 4g styles in here */
88 88 }
89 89
90 90 /* Android targeting */
91 91 @media only screen and (-webkit-device-pixel-ratio:.75){
92 92 /* Put CSS for low density (ldpi) Android layouts in here */
93 93 }
94 94 @media only screen and (-webkit-device-pixel-ratio:1){
95 95 /* Put CSS for medium density (mdpi) Android layouts in here */
96 96 }
97 97 @media only screen and (-webkit-device-pixel-ratio:1.5){
98 98 /* Put CSS for high density (hdpi) Android layouts in here */
99 99 }
100 100 /* end Android targeting */
101 101
102 102 </style>
103 103
104 104 <!-- Targeting Windows Mobile -->
105 105 <!--[if IEMobile 7]>
106 106 <style type="text/css">
107 107
108 108 </style>
109 109 <![endif]-->
110 110
111 111 <!--[if gte mso 9]>
112 112 <style>
113 113 /* Target Outlook 2007 and 2010 */
114 114 </style>
115 115 <![endif]-->
116 116 </head>
117 117 <body>
118 118 <!-- Wrapper/Container Table: Use a wrapper table to control the width and the background color consistently of your email. Use this approach instead of setting attributes on the body tag. -->
119 119 <table cellpadding="0" cellspacing="0" border="0" id="backgroundTable" align="left" style="margin:1%;width:97%;padding:0;font-family:sans-serif;font-weight:100;border:1px solid #dbd9da">
120 120 <tr>
121 121 <td valign="top" style="padding:0;">
122 122 <table cellpadding="0" cellspacing="0" border="0" align="left" width="100%">
123 123 <tr><td style="width:100%;padding:7px;background-color:#202020" valign="top">
124 124 <a style="color:#eeeeee;text-decoration:none;" href="${instance_url}">
125 125 ${'RhodeCode'}
126 126 </a>
127 127 </td></tr>
128 128 <tr>
129 129 <td style="padding:15px;" valign="top">
130 130 % for commit in data['push']['commits']:
131 131 <a href="${commit['url']}">${commit['short_id']}</a> by ${commit['author']} at ${commit['date']} <br/>
132 132 ${commit['message_html']} <br/>
133 133 <br/>
134 134 % endfor
135 135 </td>
136 136 </tr>
137 137 </table>
138 138 </td>
139 139 </tr>
140 140 </table>
141 141 <!-- End of wrapper table -->
142 142 <p><a style="margin-top:15px;margin-left:1%;font-family:sans-serif;font-weight:100;font-size:11px;color:#666666;text-decoration:none;" href="${instance_url}">
143 143 ${'This is a notification from RhodeCode. %(instance_url)s' % {'instance_url': instance_url}}
144 144 </a></p>
145 145 </body>
146 146 </html>
147 147 ''')
148 148
149 149 email_icon = '''
150 150 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
151 151 <svg
152 152 xmlns:dc="http://purl.org/dc/elements/1.1/"
153 153 xmlns:cc="http://creativecommons.org/ns#"
154 154 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
155 155 xmlns:svg="http://www.w3.org/2000/svg"
156 156 xmlns="http://www.w3.org/2000/svg"
157 157 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
158 158 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
159 159 viewBox="0 -256 1850 1850"
160 160 id="svg2989"
161 161 version="1.1"
162 162 inkscape:version="0.48.3.1 r9886"
163 163 width="100%"
164 164 height="100%"
165 165 sodipodi:docname="envelope_font_awesome.svg">
166 166 <metadata
167 167 id="metadata2999">
168 168 <rdf:RDF>
169 169 <cc:Work
170 170 rdf:about="">
171 171 <dc:format>image/svg+xml</dc:format>
172 172 <dc:type
173 173 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
174 174 </cc:Work>
175 175 </rdf:RDF>
176 176 </metadata>
177 177 <defs
178 178 id="defs2997" />
179 179 <sodipodi:namedview
180 180 pagecolor="#ffffff"
181 181 bordercolor="#666666"
182 182 borderopacity="1"
183 183 objecttolerance="10"
184 184 gridtolerance="10"
185 185 guidetolerance="10"
186 186 inkscape:pageopacity="0"
187 187 inkscape:pageshadow="2"
188 188 inkscape:window-width="640"
189 189 inkscape:window-height="480"
190 190 id="namedview2995"
191 191 showgrid="false"
192 192 inkscape:zoom="0.13169643"
193 193 inkscape:cx="896"
194 194 inkscape:cy="896"
195 195 inkscape:window-x="0"
196 196 inkscape:window-y="25"
197 197 inkscape:window-maximized="0"
198 198 inkscape:current-layer="svg2989" />
199 199 <g
200 200 transform="matrix(1,0,0,-1,37.966102,1282.678)"
201 201 id="g2991">
202 202 <path
203 203 d="m 1664,32 v 768 q -32,-36 -69,-66 -268,-206 -426,-338 -51,-43 -83,-67 -32,-24 -86.5,-48.5 Q 945,256 897,256 h -1 -1 Q 847,256 792.5,280.5 738,305 706,329 674,353 623,396 465,528 197,734 160,764 128,800 V 32 Q 128,19 137.5,9.5 147,0 160,0 h 1472 q 13,0 22.5,9.5 9.5,9.5 9.5,22.5 z m 0,1051 v 11 13.5 q 0,0 -0.5,13 -0.5,13 -3,12.5 -2.5,-0.5 -5.5,9 -3,9.5 -9,7.5 -6,-2 -14,2.5 H 160 q -13,0 -22.5,-9.5 Q 128,1133 128,1120 128,952 275,836 468,684 676,519 682,514 711,489.5 740,465 757,452 774,439 801.5,420.5 829,402 852,393 q 23,-9 43,-9 h 1 1 q 20,0 43,9 23,9 50.5,27.5 27.5,18.5 44.5,31.5 17,13 46,37.5 29,24.5 35,29.5 208,165 401,317 54,43 100.5,115.5 46.5,72.5 46.5,131.5 z m 128,37 V 32 q 0,-66 -47,-113 -47,-47 -113,-47 H 160 Q 94,-128 47,-81 0,-34 0,32 v 1088 q 0,66 47,113 47,47 113,47 h 1472 q 66,0 113,-47 47,-47 47,-113 z"
204 204 id="path2993"
205 205 inkscape:connector-curvature="0"
206 206 style="fill:currentColor" />
207 207 </g>
208 208 </svg>
209 209 '''
210 210
211
211 212 class EmailSettingsSchema(colander.Schema):
212 213 @colander.instantiate(validator=colander.Length(min=1))
213 214 class recipients(colander.SequenceSchema):
214 215 title = _('Recipients')
215 216 description = _('Email addresses to send push events to')
216 217 widget = deform.widget.SequenceWidget(min_len=1)
217 218
218 219 recipient = colander.SchemaNode(
219 220 colander.String(),
220 221 title=_('Email address'),
221 222 description=_('Email address'),
222 223 default='',
223 224 validator=colander.Email(),
224 225 widget=deform.widget.TextInputWidget(
225 226 placeholder='user@domain.com',
226 227 ),
227 228 )
228 229
229 230
230 231 class EmailIntegrationType(IntegrationTypeBase):
231 232 key = 'email'
232 233 display_name = _('Email')
233 234 description = _('Send repo push summaries to a list of recipients via email')
234 235 icon = email_icon
235 236
236 237 def settings_schema(self):
237 238 schema = EmailSettingsSchema()
238 239 return schema
239 240
240 241 def send_event(self, event):
241 242 data = event.as_dict()
242 243 log.debug('got event: %r', event)
243 244
244 245 if isinstance(event, events.RepoPushEvent):
245 246 repo_push_handler(data, self.settings)
246 247 else:
247 248 log.debug('ignoring event: %r', event)
248 249
249 250
250 251 def repo_push_handler(data, settings):
251 252 commit_num = len(data['push']['commits'])
252 253 server_url = data['server_url']
253 254
254 if commit_num == 0:
255 subject = '[{repo_name}] {author} pushed {commit_num} commit on branches: {branches}'.format(
255 if commit_num == 1:
256 if data['push']['branches']:
257 _subject = '[{repo_name}] {author} pushed {commit_num} commit on branches: {branches}'
258 else:
259 _subject = '[{repo_name}] {author} pushed {commit_num} commit'
260 subject = _subject.format(
256 261 author=data['actor']['username'],
257 262 repo_name=data['repo']['repo_name'],
258 263 commit_num=commit_num,
259 264 branches=', '.join(
260 265 branch['name'] for branch in data['push']['branches'])
261 266 )
262 267 else:
263 subject = '[{repo_name}] {author} pushed {commit_num} commits on branches: {branches}'.format(
268 if data['push']['branches']:
269 _subject = '[{repo_name}] {author} pushed {commit_num} commits on branches: {branches}'
270 else:
271 _subject = '[{repo_name}] {author} pushed {commit_num} commits'
272 subject = _subject.format(
264 273 author=data['actor']['username'],
265 274 repo_name=data['repo']['repo_name'],
266 275 commit_num=commit_num,
267 276 branches=', '.join(
268 277 branch['name'] for branch in data['push']['branches']))
269 278
270 279 email_body_plaintext = repo_push_template_plaintext.render(
271 280 data=data,
272 281 subject=subject,
273 282 instance_url=server_url)
274 283
275 284 email_body_html = repo_push_template_html.render(
276 285 data=data,
277 286 subject=subject,
278 287 instance_url=server_url)
279 288
280 289 for email_address in settings['recipients']:
281 290 run_task(
282 291 tasks.send_email, email_address, subject,
283 292 email_body_plaintext, email_body_html)
General Comments 0
You need to be logged in to leave comments. Login now