Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# -*- coding: utf-8 -*- 

2""" 

3@file 

4@brief Functions to dump emails 

5""" 

6import os 

7import datetime 

8import json 

9from jinja2 import Template 

10from pyquickhelper.loghelper import noLOG 

11from ..helpers import iterator_prev_next 

12from .renderer import Renderer 

13from .email_message_style import template_email_list_html_iter, template_email_list_html_begin 

14from .email_message_style import template_email_list_html_end, template_email_css 

15 

16 

17class EmailMessageListRenderer(Renderer): 

18 """ 

19 Defines a way to render a list of emails with a template 

20 template based on `Jinja2 <http://jinja.pocoo.org/docs/dev/>`_. 

21 

22 .. exref:: 

23 :title: Render a list of emails 

24 

25 The following example extracts all mails in a folder of a gmail inbox, 

26 dumps them in a folder and produces a summary which connects to them. 

27 

28 :: 

29 

30 from pymmails import EmailMessageRenderer, EmailMessageListRenderer, MailBoxImap 

31 box = MailBoxImap(user, pwd, server) 

32 box.login() 

33 mails = box.enumerate_mails_in_folder("<your_folder)") 

34 

35 email_render = EmailMessageRenderer() 

36 

37 render = EmailMessageListRenderer(title="list of mails", email_renderer=email_render) 

38 render.write(iter=mails, location=temp, filename="summary.html") 

39 box.logout()) 

40 render.flush() 

41 """ 

42 

43 def __init__(self, title, email_renderer, tmpl_begin=None, tmpl_iter=None, tmpl_end=None, 

44 css=None, style_table="dataframe100l", style_highlight="dataframe100l_hl", 

45 buffer_write=None, fLOG=noLOG): 

46 """ 

47 @param title title 

48 @param email_renderer email renderer (see @see cl EmailMessageRenderer) 

49 @param tmpl_begin template which begins the summary 

50 @param tmpl_iter template which adds an element 

51 @param tmpl_end template which ends the summary 

52 @param css template style 

53 @param style_table style for the table 

54 @param style_highlight style for highlighted cells 

55 @param buffer_write instance of class @see cl BufferFilesWriting 

56 @param fLOG logging function 

57 """ 

58 if tmpl_begin is None: 

59 _template_begin = template_email_list_html_begin 

60 elif len(tmpl_begin) < 5000 and os.path.exists(tmpl_begin): 

61 with open(tmpl_begin, "r", encoding="utf8") as f: 

62 _template_begin = f.read() 

63 else: 

64 _template_begin = tmpl_begin 

65 

66 if tmpl_iter is None: 

67 _template_iter = template_email_list_html_iter 

68 elif len(tmpl_iter) < 5000 and os.path.exists(tmpl_iter): 

69 with open(tmpl_iter, "r", encoding="utf8") as f: 

70 _template_iter = f.read() 

71 else: 

72 _template_iter = tmpl_iter 

73 

74 if tmpl_end is None: 

75 _template_end = template_email_list_html_end 

76 elif len(tmpl_end) < 5000 and os.path.exists(tmpl_end): 

77 with open(tmpl_end, "r", encoding="utf8") as f: 

78 _template_end = f.read() 

79 else: 

80 _template_end = tmpl_end 

81 

82 if css is None: 

83 _css = template_email_css 

84 elif len(css) < 5000 and os.path.exists(css): 

85 with open(css, "r", encoding="utf8") as f: 

86 _css = f.read() 

87 else: 

88 _css = css 

89 

90 if buffer_write is None: 

91 buffer_write = email_renderer.BufferWrite 

92 

93 Renderer.__init__(self, tmpl=_template_iter, css=_css, style_table=style_table, 

94 style_highlight=style_highlight, buffer_write=buffer_write, fLOG=fLOG) 

95 

96 self._email_renderer = email_renderer 

97 self._template_begin = Template(_template_begin) 

98 self._template_end = Template(_template_end) 

99 self._title = title 

100 

101 def render(self, location, iter, attachments=None, # pylint: disable=W0237 

102 file_css="mail_style.css"): 

103 """ 

104 Renders a mail. 

105 

106 @paramp location location where this mail should be saved 

107 @param iter iterator on tuple (object, function to call to render the object) 

108 @param attachments used to produce a JSON list 

109 @param file_css css file (where it is supposed to be stored) 

110 @return html, css (content), attachements as JSON 

111 

112 The method populate fields ``now``, ``message``, ``css``, ``render``, ``location``, ``title``. 

113 """ 

114 now = datetime.datetime.now() 

115 file_css = os.path.relpath(file_css, location) 

116 content = [] 

117 self.fLOG("[EmailMessageListRenderer.render] begin") 

118 css = self._css.render() 

119 h = self._template_begin.render(css=file_css, render=self, 

120 location=location, title=self._title, now=now) 

121 content.append(h) 

122 self.fLOG("[EmailMessageListRenderer.render] iterate") 

123 

124 def iter_on_mail(): 

125 "local function" 

126 for i, mail3 in enumerate(iterator_prev_next(sorted(iter))): 

127 prev, item, next = mail3 

128 if i % 10 == 9: 

129 self.fLOG( 

130 "[EmailMessageListRenderer.render] iterate", i + 1) 

131 if not isinstance(item, tuple): 

132 raise TypeError( 

133 "expects a tuple (EmailMessage, function to render) not {0}".format(type(item))) 

134 prev_mail = prev[0].default_filename() + \ 

135 ".html" if prev else None 

136 next_mail = next[0].default_filename() + \ 

137 ".html" if next else None 

138 obj, f = item 

139 f(obj, location, prev_mail, next_mail) 

140 yield prev[0] if prev else None, item[0], next[0] if next else None 

141 

142 for _, item, __ in iter_on_mail(): 

143 h = self._template.render(message=item, css=file_css, render=self, location=location, 

144 title=self._title, url=item.default_filename() + ".html", now=now) 

145 content.append(h) 

146 

147 self.fLOG("[EmailMessageListRenderer.render] end") 

148 h = self._template_end.render(css=file_css, render=self, 

149 location=location, title=self._title, now=now) 

150 json_attachments = [] 

151 if attachments is not None: 

152 for att in attachments: 

153 satt = att.replace("\\", "/") 

154 json_attachments.append(dict(a=satt, name=satt)) 

155 content.append(h) 

156 return "\n".join(content), css, json_attachments 

157 

158 def write(self, location, iter, filename, attachments=None, # pylint: disable=W0221 

159 overwrite=False, file_css="mail_style.css", 

160 file_jsatt="_summaryattachements.json", encoding="utf8", 

161 attach_folder="attachments"): 

162 """ 

163 Writes a list of mails in a folder and writes a summary. 

164 

165 @param location location 

166 @param mail instance of @see cl EmailMessage 

167 @param attachments list of attachments (see @see me dump_attachments) 

168 @param overwrite the function does not overwrite 

169 @param file_css css file (where it is supposed to be stored) 

170 @param file_jsatt list of attachments in json format 

171 ``[{'a': 'href', 'name': 'anchor', ...}, ...]`` 

172 @param encoding encoding 

173 @param attach_folder attachments folder 

174 @return list of written local files 

175 

176 The method calls method :meth:`flush 

177 <pymmails.helpers.buffer_files_writing.BufferFilesWriting.flush>`. 

178 """ 

179 if not hasattr(iter, '__iter__'): 

180 raise TypeError("class {0} is not iterable".format(type(iter))) 

181 

182 full_css = os.path.join(location, file_css) 

183 full_mail = os.path.join(location, filename) 

184 full_file_jsatt = os.path.join(location, file_jsatt) 

185 if self.BufferWrite.exists(full_css, local=not overwrite) and \ 

186 self.BufferWrite.exists(full_mail, local=not overwrite): 

187 self.fLOG("[EmailMessageListRenderer.write] already exist css='{0}' html='{1}']".format( 

188 full_css, full_mail)) 

189 return [full_mail, full_css] 

190 

191 def fwrite(message, location, prev_mail, next_mail): 

192 "local function" 

193 res = message.dump(self._email_renderer, location=location, 

194 prev_mail=prev_mail, next_mail=next_mail, fLOG=self.fLOG, 

195 overwrite=overwrite, attach_folder=attach_folder) 

196 html, css = res[0] 

197 atts = res[1] 

198 return html, css, atts 

199 

200 def walk_iter(): 

201 "local function" 

202 for obj in iter: 

203 yield obj, fwrite 

204 

205 html, css, json_att = self.render( 

206 location, walk_iter(), file_css=full_css) 

207 wrote = [] 

208 if not self.BufferWrite.exists(full_css, local=not overwrite): 

209 f = self.BufferWrite.open(full_css, text=True, encoding=encoding) 

210 f.write(css) 

211 wrote.append(full_css) 

212 if not self.BufferWrite.exists(full_mail, local=not overwrite): 

213 f = self.BufferWrite.open(full_mail, text=True, encoding=encoding) 

214 f.write(html) 

215 wrote.append(full_mail) 

216 if json_att and not self.BufferWrite.exists(full_file_jsatt, local=not overwrite): 

217 f = self.BufferWrite.open( 

218 full_file_jsatt, text=True, encoding=encoding) 

219 js = json.dumps(json_att) 

220 f.write(js) 

221 wrote.append(full_file_jsatt) 

222 return wrote