Wiki source code of LoadingGroovy
Last modified by Ludovic Dubost on 2009/10/18 22:11
Show last authors
author | version | line-number | content |
---|---|---|---|
1 | |||
2 | import java.util.*; | ||
3 | import javax.mail.Folder; | ||
4 | import com.xpn.xwiki.doc.*; | ||
5 | import com.xpn.xwiki.*; | ||
6 | import com.xpn.xwiki.util.Util; | ||
7 | import java.io.*; | ||
8 | import javax.mail.*; | ||
9 | |||
10 | public class LoadRecruitmentContactGroovy { | ||
11 | def context; | ||
12 | def xwiki; | ||
13 | def protocol; | ||
14 | def server; | ||
15 | def user; | ||
16 | def pass; | ||
17 | def defaultUser; | ||
18 | def debug = ""; | ||
19 | |||
20 | public isInstalled() { | ||
21 | return "yes"; | ||
22 | } | ||
23 | |||
24 | public addDebug(message) { | ||
25 | debug += message + "\n"; | ||
26 | } | ||
27 | |||
28 | public getDebug() { | ||
29 | return debug; | ||
30 | } | ||
31 | |||
32 | public void setContext(context, xwiki) { | ||
33 | this.context = context; | ||
34 | this.xwiki = xwiki; | ||
35 | } | ||
36 | |||
37 | public String getLoadingUser() { | ||
38 | if (defaultUser==null || defaultUser=="") | ||
39 | return "XWiki.Admin"; | ||
40 | else | ||
41 | return defaultUser; | ||
42 | } | ||
43 | |||
44 | public void setMailServerFromPage(page) { | ||
45 | def settingsDoc = xwiki.getDocument(page); | ||
46 | settingsDoc.use("RecruitmentCode.SettingsClass"); | ||
47 | this.protocol = settingsDoc.getValue("mailprotocol"); | ||
48 | this.server = settingsDoc.getValue("mailserver"); | ||
49 | this.user = settingsDoc.getValue("mailuser"); | ||
50 | |||
51 | if (this.server.contains("gmail.com")) | ||
52 | this.user = "recent:" + this.user; | ||
53 | |||
54 | this.pass = settingsDoc.getValue("mailpassword"); | ||
55 | this.defaultUser = settingsDoc.getValue("user"); | ||
56 | } | ||
57 | |||
58 | public void setMailServer(protocol, server, user, pass) { | ||
59 | this.protocol = protocol; | ||
60 | this.server = server; | ||
61 | this.user = user; | ||
62 | this.pass = pass; | ||
63 | } | ||
64 | |||
65 | public int checkContacts() { | ||
66 | try { | ||
67 | return xwiki.mail.checkMail(protocol, server, user, pass) | ||
68 | } catch (Throwable e) { | ||
69 | addDebug("Failed to connect to mail server " + e.getMessage()) | ||
70 | return -1; | ||
71 | } | ||
72 | } | ||
73 | |||
74 | public boolean loadContact(mail, confirm) { | ||
75 | addDebug("Getting mail content"); | ||
76 | def bodypart = mail.getContent(); | ||
77 | def content = getMailContent(bodypart); | ||
78 | if (content.length()>50000) { | ||
79 | content = content.substring(0, 50000); | ||
80 | addDebug("Content to big: " + content); | ||
81 | } | ||
82 | |||
83 | def address = getMailAddress(mail, mail.getContent()); | ||
84 | |||
85 | def name = address.personal; | ||
86 | def fname = ""; | ||
87 | def lname = ""; | ||
88 | |||
89 | def pos = name.indexOf(" "); | ||
90 | if (pos != -1) { | ||
91 | fname = name.substring(0, pos); | ||
92 | lname = name.substring(pos + 1); | ||
93 | } else { | ||
94 | fname = ""; | ||
95 | lname = name; | ||
96 | } | ||
97 | |||
98 | addDebug("Extracted name: " + name + " - " + fname + " - " + lname); | ||
99 | |||
100 | def wikiname = xwiki.clearName(name.replaceAll(" ","")); | ||
101 | |||
102 | addDebug("Wiki name: " + wikiname); | ||
103 | |||
104 | if (wikiname=="") { | ||
105 | addDebug("No name extracted"); | ||
106 | return false; | ||
107 | } | ||
108 | |||
109 | def contactDoc = xwiki.getDocument("Recruitment.$wikiname") | ||
110 | boolean alreadyLoaded = false; | ||
111 | if (!contactDoc.isNew()) { | ||
112 | contactDoc.use("RecruitmentCode.CandidateClass") | ||
113 | def pfname = contactDoc.getValue("first_name") | ||
114 | def plname = contactDoc.getValue("last_name") | ||
115 | if (pfname==fname && plname==lname) { | ||
116 | alreadyLoaded = true; | ||
117 | addDebug("contact exist: " + wikiname); | ||
118 | } else { | ||
119 | if (pfname!=fname) | ||
120 | addDebug("fname different"); | ||
121 | if (plname!=lname) | ||
122 | addDebug("lname different"); | ||
123 | return false; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | if (!alreadyLoaded) { | ||
128 | def pagename = xwiki.getUniquePageName("Recruitment", wikiname) | ||
129 | contactDoc = xwiki.getDocument("Recruitment.${pagename}") | ||
130 | contactDoc.use(contactDoc.newObject("RecruitmentCode.CandidateClass")) | ||
131 | contactDoc.set("first_name", fname) | ||
132 | contactDoc.set("last_name", lname) | ||
133 | contactDoc.set("email", address.getAddress()) | ||
134 | contactDoc.set("status", "none") | ||
135 | contactDoc.set("rating", -1) | ||
136 | contactDoc.set("details", content) | ||
137 | contactDoc.setContent(xwiki.getDocument("RecruitmentCode.CandidateClassTemplate").getContent()) | ||
138 | contactDoc.setTitle("Candidate ${name}") | ||
139 | contactDoc.setComment("Added candidate from email") | ||
140 | |||
141 | // addDebug("User: " + pagename + "-" + contactDoc.email + "-" + contactDoc.download + "-" + contactDoc.downloaddate + "-" + contactDoc.downloadreason + "-" + contactDoc.first_name + "-" + contactDoc.last_name + "-" + contactDoc.officephone + "-" + contactDoc.country) | ||
142 | contactDoc.use(contactDoc.newObject("XWiki.Tags")) | ||
143 | contactDoc.set("tags", "candidate") | ||
144 | if (confirm) { | ||
145 | context.getContext().setUser(getLoadingUser()) | ||
146 | contactDoc.save() | ||
147 | |||
148 | def bodyparts = xwiki.getArrayList(); | ||
149 | def nbAttachs = getMailAttachments(bodypart, bodyparts); | ||
150 | addDebug("Attaching " + nbAttachs + " attachments"); | ||
151 | try { | ||
152 | addAttachmentFromMail(contactDoc, bodyparts, context); | ||
153 | } catch (Exception e) { | ||
154 | e.printStackTrace() | ||
155 | addDebug("Failed to attach files to email with exception " + e.getMessage()) | ||
156 | } | ||
157 | return true; | ||
158 | } | ||
159 | } else { | ||
160 | addDebug("Contact already loaded"); | ||
161 | return false; | ||
162 | } | ||
163 | |||
164 | } | ||
165 | |||
166 | public boolean loadContacts(int nb, withDelete) { | ||
167 | try { | ||
168 | |||
169 | def loadingUserDoc = xwiki.getDocument(getLoadingUser()); | ||
170 | if (loadingUserDoc.isNew() || !loadingUserDoc.getObject("XWiki.XWikiUsers")) { | ||
171 | addDebug("Loading user set in Settings does not exist. Cannot load emails") | ||
172 | return false; | ||
173 | } | ||
174 | |||
175 | // Get a session. Use a blank Properties object. | ||
176 | def props = new Properties(); | ||
177 | // necessary to work with Gmail | ||
178 | props.put("mail.imap.partialfetch", "false"); | ||
179 | props.put("mail.imaps.partialfetch", "false"); | ||
180 | def session = Session.getInstance(props); | ||
181 | // Get a Store object | ||
182 | def store = session.getStore(protocol); | ||
183 | |||
184 | store.connect(server, user, pass) | ||
185 | def fldr = store.getFolder("INBOX") | ||
186 | fldr.open(Folder.READ_WRITE) | ||
187 | |||
188 | if (fldr.getMessageCount()< nb) | ||
189 | nb = fldr.getMessageCount() | ||
190 | def messages = fldr.getMessages(1, nb) | ||
191 | for(mail in messages) { | ||
192 | try { | ||
193 | addDebug("Loading mail") | ||
194 | if (loadContact(mail, true)==true) { | ||
195 | if (withDelete==true) { | ||
196 | mail.setFlag(Flags.Flag.DELETED, true); | ||
197 | } | ||
198 | } | ||
199 | } catch (Exception e) { | ||
200 | addDebug("Failed to load mail with exception " + e.getMessage()) | ||
201 | } | ||
202 | } | ||
203 | if (withDelete) { | ||
204 | fldr.close(true); | ||
205 | } else { | ||
206 | fldr.close(false); | ||
207 | } | ||
208 | store.close(); | ||
209 | System.out.println(getDebug()); | ||
210 | return true; | ||
211 | } catch (Throwable e) { | ||
212 | addDebug("Failed to load emails with exception " + e.getMessage()) | ||
213 | return false; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | |||
218 | public int addAttachments(doc1, context1) { | ||
219 | def doc = doc1.document; | ||
220 | def context = context1.context; | ||
221 | def xwiki = context.getWiki() | ||
222 | int nb = 0; | ||
223 | def fileupload = xwiki.getPlugin("fileupload",context) | ||
224 | for (fileitem in fileupload.getFileItems(context)) { | ||
225 | if (!fileitem.isFormField()) { | ||
226 | def name = fileitem.fieldName | ||
227 | byte[] data = fileupload.getFileItemData(name, context); | ||
228 | if ((data!=null)&&(data.length>0)) { | ||
229 | String fname = fileupload.getFileName(name, context); | ||
230 | int i = fname.lastIndexOf("\\"); | ||
231 | if (i==-1) | ||
232 | i = fname.lastIndexOf("/"); | ||
233 | def filename = fname.substring(i+1); | ||
234 | filename = filename.replaceAll("\\+"," "); | ||
235 | def attachment = new XWikiAttachment(); | ||
236 | doc.getAttachmentList().add(attachment); | ||
237 | attachment.setContent(data); | ||
238 | attachment.setFilename(filename); | ||
239 | // TODO: handle Author | ||
240 | attachment.setAuthor(context1.user); | ||
241 | // Add the attachment to the document | ||
242 | attachment.setDoc(doc); | ||
243 | doc.saveAttachmentContent(attachment, context); | ||
244 | nb++; | ||
245 | } | ||
246 | } | ||
247 | } | ||
248 | return nb; | ||
249 | } | ||
250 | |||
251 | public int addAttachmentFromMail(doc1, afilename, adata, context1) { | ||
252 | def fname = afilename; | ||
253 | int i = fname.lastIndexOf("\\"); | ||
254 | if (i==-1) | ||
255 | i = fname.lastIndexOf("/"); | ||
256 | def filename = fname.substring(i+1); | ||
257 | filename = filename.replaceAll("\\+"," "); | ||
258 | |||
259 | addDebug("adding attachment: " + filename); | ||
260 | |||
261 | def doc = doc1.getDocument(); | ||
262 | def context = context1.getContext(); | ||
263 | def xwiki = context.getWiki() | ||
264 | def attachment = new XWikiAttachment(); | ||
265 | doc.getAttachmentList().add(attachment); | ||
266 | attachment.setContent(adata); | ||
267 | attachment.setFilename(filename); | ||
268 | // TODO: handle Author | ||
269 | attachment.setAuthor(context1.user); | ||
270 | // Add the attachment to the document | ||
271 | attachment.setDoc(doc); | ||
272 | addDebug("saving attachment: " + filename); | ||
273 | doc.saveAttachmentContent(attachment, context); | ||
274 | return 1; | ||
275 | } | ||
276 | |||
277 | public int addAttachmentFromMail(doc1, bodyparts, context1) { | ||
278 | def nb = 0; | ||
279 | for(bodypart in bodyparts) { | ||
280 | String fileName = bodypart.getFileName(); | ||
281 | addDebug("Treating attachment: " + fileName); | ||
282 | if (fileName==null) | ||
283 | fileName = "fichier.doc" | ||
284 | String disposition = bodypart.getDisposition(); | ||
285 | String contentType = bodypart.getContentType().toLowerCase(); | ||
286 | |||
287 | addDebug("Treating attachment of type: " + bodypart.getContentType()); | ||
288 | |||
289 | def baos = new ByteArrayOutputStream(); | ||
290 | OutputStream out = new BufferedOutputStream(baos); | ||
291 | // We can't just use p.writeTo() here because it doesn't | ||
292 | // decode the attachment. Instead we copy the input stream | ||
293 | // onto the output stream which does automatically decode | ||
294 | // Base-64, quoted printable, and a variety of other formats. | ||
295 | InputStream ins = new BufferedInputStream(bodypart.getInputStream()); | ||
296 | int b = ins.read() | ||
297 | while (b != -1) { | ||
298 | out.write(b); | ||
299 | b = ins.read(); | ||
300 | } | ||
301 | out.flush(); | ||
302 | out.close(); | ||
303 | ins.close(); | ||
304 | |||
305 | addDebug("Treating attachment step 3: " + fileName); | ||
306 | |||
307 | byte[] data = baos.toByteArray(); | ||
308 | addDebug("Ready to attach attachment: " + fileName); | ||
309 | nb += addAttachmentFromMail(doc1, fileName, data, context1); | ||
310 | } | ||
311 | return nb; | ||
312 | } | ||
313 | |||
314 | public String getMailContent(bodypart) { | ||
315 | String content = "" | ||
316 | try { | ||
317 | def mcount = bodypart.getCount(); | ||
318 | def i = 0; | ||
319 | while (i<mcount) { | ||
320 | def newbodypart = bodypart.getBodyPart(i) | ||
321 | if(newbodypart.getContentType().toLowerCase().contains("vcard")) { | ||
322 | addDebug("Adding vcard to content"); | ||
323 | if (!content.toLowerCase().contains("xwiki")) | ||
324 | content = "${content} ${newbodypart.content}" | ||
325 | } else if(newbodypart.getContentType().toLowerCase().startsWith("text/")) { | ||
326 | addDebug("Adding text to content"); | ||
327 | // addDebug("Adding text to content (type is " + newbodypart.getContentType().toLowerCase() + "): " + newbodypart.content); | ||
328 | content = "${content} ${newbodypart.content}" | ||
329 | } | ||
330 | |||
331 | |||
332 | if(newbodypart.getContentType().toLowerCase().startsWith("multipart/")) { | ||
333 | addDebug("Adding multipart to content"); | ||
334 | def ncontent = getMailContent(newbodypart.content) | ||
335 | if (ncontent!="") | ||
336 | content = "${content} ${ncontent}" | ||
337 | } | ||
338 | |||
339 | if (newbodypart.getContentType().toLowerCase().startsWith("message/rfc822")) { | ||
340 | addDebug("Adding rfc822 to content"); | ||
341 | def ncontent = getMailContent(newbodypart.content.content) | ||
342 | if (ncontent!="") | ||
343 | content = "${content} ${ncontent}" | ||
344 | } | ||
345 | |||
346 | i++; | ||
347 | } | ||
348 | |||
349 | return content; | ||
350 | } catch (Exception e) { | ||
351 | addDebug("Failed to get Mail Content " + e.getMessage()); | ||
352 | e.printStackTrace(); | ||
353 | return "Failed to get Mail Content"; | ||
354 | } | ||
355 | } | ||
356 | |||
357 | |||
358 | public int getMailAttachments(bodypart, bodyparts) { | ||
359 | try { | ||
360 | def nb = 0; | ||
361 | def mcount = bodypart.getCount(); | ||
362 | def i = 0; | ||
363 | while (i<mcount) { | ||
364 | def newbodypart = bodypart.getBodyPart(i) | ||
365 | |||
366 | if(newbodypart.getContentType().toLowerCase().startsWith("application/")) { | ||
367 | nb++; | ||
368 | bodyparts.add(newbodypart) | ||
369 | } | ||
370 | |||
371 | if(newbodypart.getContentType().toLowerCase().startsWith("multipart/")) { | ||
372 | nb += getMailAttachments(newbodypart.content,bodyparts) | ||
373 | } | ||
374 | |||
375 | if(newbodypart.getContentType().toLowerCase().startsWith("message/rfc822")) { | ||
376 | nb += getMailAttachments(newbodypart.content.content,bodyparts) | ||
377 | } | ||
378 | |||
379 | i++; | ||
380 | } | ||
381 | return nb; | ||
382 | } catch (Exception e) { | ||
383 | return 0; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | public Object getMailAddress(message, bodypart) { | ||
388 | def address = (message==null) ? "" : message.getFrom()[0]; | ||
389 | addDebug("Found address: " + address); | ||
390 | try { | ||
391 | def mcount = bodypart.getCount(); | ||
392 | addDebug("Found body parts: " + mcount); | ||
393 | def i = 0; | ||
394 | while (i<mcount) { | ||
395 | def newbodypart = bodypart.getBodyPart(i) | ||
396 | |||
397 | addDebug("Checking body part " + i + " " + newbodypart.getContentType().toLowerCase()); | ||
398 | |||
399 | if(newbodypart.getContentType().toLowerCase().startsWith("multipart/")) { | ||
400 | def add = getMailAddress(null, newbodypart.content) | ||
401 | addDebug("Found address in multipart: " + add); | ||
402 | if ((add!=null)&&(add!="")) | ||
403 | address = add; | ||
404 | } | ||
405 | |||
406 | if (newbodypart.getContentType().toLowerCase().startsWith("message/rfc822")) { | ||
407 | def add = getMailAddress(newbodypart.content, newbodypart.content.content) | ||
408 | addDebug("Found address in rfc822: " + add); | ||
409 | if ((add!=null)&&(add!="")) | ||
410 | address = add; | ||
411 | } | ||
412 | |||
413 | i++; | ||
414 | } | ||
415 | return address; | ||
416 | } catch (Exception e) { | ||
417 | return address; | ||
418 | } | ||
419 | } | ||
420 | |||
421 | public Map readMail(content) { | ||
422 | def map = new HashMap(); | ||
423 | def lines = content.split("\n") | ||
424 | for (line in lines) { | ||
425 | def i = line.indexOf("="); | ||
426 | if (i!=-1) { | ||
427 | def key = line.substring(0, i).trim(); | ||
428 | def value = line.substring(i+1).trim(); | ||
429 | if (mapping.get(key)) | ||
430 | key = mapping.get(key); | ||
431 | map.put(key, value); | ||
432 | } | ||
433 | } | ||
434 | return map; | ||
435 | } | ||
436 | |||
437 | |||
438 | } |