19 package org.sleuthkit.autopsy.thunderbirdparser;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.HashSet;
26 import java.util.List;
28 import java.util.logging.Level;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31 import org.openide.util.NbBundle;
32 import org.openide.util.NbBundle.Messages;
52 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
88 if (abstractFile.getKnown().equals(TskData.FileKnown.KNOWN)) {
93 if ((abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)) ||
94 (abstractFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK))) {
98 if ((abstractFile.isFile() ==
false)) {
103 boolean isMbox =
false;
105 byte[] t =
new byte[64];
106 if (abstractFile.getSize() > 64) {
107 int byteRead = abstractFile.read(t, 0, 64);
109 isMbox = MboxParser.isValidMimeTypeMbox(t);
112 }
catch (TskException ex) {
113 logger.log(Level.WARNING, null, ex);
120 if (PstParser.isPstFile(abstractFile)) {
134 @Messages({
"ThunderbirdMboxFileIngestModule.processPst.indexError.message=Failed to index encryption detected artifact for keyword search."})
136 String fileName =
getTempPath() + File.separator + abstractFile.getName()
137 +
"-" + String.valueOf(abstractFile.getId());
138 File file =
new File(fileName);
142 logger.log(Level.WARNING,
"Not enough disk space to write file to disk.");
144 NbBundle.getMessage(this.getClass(),
145 "ThunderbirdMboxFileIngestModule.processPst.errMsg.outOfDiskSpace",
146 abstractFile.getName()));
153 }
catch (IOException ex) {
154 logger.log(Level.WARNING,
"Failed writing pst file to disk.", ex);
158 PstParser parser =
new PstParser(services);
159 PstParser.ParseResult result = parser.parse(file, abstractFile.getId());
161 if (result == PstParser.ParseResult.OK) {
164 }
else if (result == PstParser.ParseResult.ENCRYPT) {
167 BlackboardArtifact artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED);
168 artifact.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
EmailParserModuleFactory.getModuleName(), NbBundle.getMessage(this.getClass(),
"ThunderbirdMboxFileIngestModule.encryptionFileLevel")));
175 logger.log(Level.SEVERE,
"Unable to index blackboard artifact " + artifact.getArtifactID(), ex);
179 }
catch (TskCoreException ex) {
180 logger.log(Level.INFO,
"Failed to add encryption attribute to file: {0}", abstractFile.getName());
185 NbBundle.getMessage(
this.getClass(),
"ThunderbirdMboxFileIngestModule.processPst.errProcFile.msg",
186 abstractFile.getName()),
187 NbBundle.getMessage(
this.getClass(),
188 "ThunderbirdMboxFileIngestModule.processPst.errProcFile.details"));
189 logger.log(Level.INFO,
"PSTParser failed to parse {0}", abstractFile.getName());
193 if (file.delete() ==
false) {
194 logger.log(Level.INFO,
"Failed to delete temp file: {0}", file.getName());
197 String errors = parser.getErrors();
198 if (errors.isEmpty() ==
false) {
200 NbBundle.getMessage(
this.getClass(),
"ThunderbirdMboxFileIngestModule.processPst.errProcFile.msg2",
201 abstractFile.getName()), errors);
215 String mboxFileName = abstractFile.getName();
216 String mboxParentDir = abstractFile.getParentPath();
218 String emailFolder =
"";
220 if (mboxParentDir.contains(
"/Mail/")) {
221 emailFolder = mboxParentDir.substring(mboxParentDir.indexOf(
"/Mail/") + 5);
222 }
else if (mboxParentDir.contains(
"/ImapMail/")) {
223 emailFolder = mboxParentDir.substring(mboxParentDir.indexOf(
"/ImapMail/") + 9);
225 emailFolder = emailFolder + mboxFileName;
226 emailFolder = emailFolder.replaceAll(
".sbd",
"");
228 String fileName =
getTempPath() + File.separator + abstractFile.getName()
229 +
"-" + String.valueOf(abstractFile.getId());
230 File file =
new File(fileName);
234 logger.log(Level.WARNING,
"Not enough disk space to write file to disk.");
236 NbBundle.getMessage(
this.getClass(),
"ThunderbirdMboxFileIngestModule.processMBox.errProcFile.msg",
237 abstractFile.getName()),
238 NbBundle.getMessage(
this.getClass(),
239 "ThunderbirdMboxFileIngestModule.processMBox.errProfFile.details"));
245 }
catch (IOException ex) {
246 logger.log(Level.WARNING,
"Failed writing mbox file to disk.", ex);
250 MboxParser parser =
new MboxParser(services, emailFolder);
251 List<EmailMessage> emails = parser.parse(file, abstractFile.getId());
254 if (file.delete() ==
false) {
255 logger.log(Level.INFO,
"Failed to delete temp file: {0}", file.getName());
258 String errors = parser.getErrors();
259 if (errors.isEmpty() ==
false) {
261 NbBundle.getMessage(
this.getClass(),
"ThunderbirdMboxFileIngestModule.processMBox.errProcFile.msg2",
262 abstractFile.getName()), errors);
276 File dir =
new File(tmpDir);
277 if (dir.exists() ==
false) {
286 File dir =
new File(outDir);
287 if (dir.exists() ==
false) {
305 private void processEmails(List<EmailMessage> emails, AbstractFile abstractFile) {
306 List<AbstractFile> derivedFiles =
new ArrayList<>();
310 for (EmailMessage email : emails) {
311 BlackboardArtifact msgArtifact =
addArtifact(email, abstractFile);
313 if ((msgArtifact != null) && (email.hasAttachment())) {
314 derivedFiles.addAll(
handleAttachments(email.getAttachments(), abstractFile, msgArtifact ));
318 if (derivedFiles.isEmpty() ==
false) {
319 for (AbstractFile derived : derivedFiles) {
337 private List<AbstractFile>
handleAttachments(List<EmailMessage.Attachment> attachments, AbstractFile abstractFile, BlackboardArtifact messageArtifact) {
338 List<AbstractFile> files =
new ArrayList<>();
339 for (EmailMessage.Attachment attach : attachments) {
340 String filename = attach.getName();
341 long crTime = attach.getCrTime();
342 long mTime = attach.getmTime();
343 long aTime = attach.getaTime();
344 long cTime = attach.getcTime();
345 String relPath = attach.getLocalPath();
346 long size = attach.getSize();
347 TskData.EncodingType encodingType = attach.getEncodingType();
351 size, cTime, crTime, aTime, mTime,
true, messageArtifact,
"",
354 }
catch (TskCoreException ex) {
356 NbBundle.getMessage(
this.getClass(),
"ThunderbirdMboxFileIngestModule.handleAttch.errMsg",
357 abstractFile.getName()),
358 NbBundle.getMessage(
this.getClass(),
359 "ThunderbirdMboxFileIngestModule.handleAttch.errMsg.details", filename));
360 logger.log(Level.INFO,
"", ex);
374 Pattern p = Pattern.compile(
"\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}\\b",
375 Pattern.CASE_INSENSITIVE);
376 Matcher m = p.matcher(input);
377 Set<String> emailAddresses =
new HashSet<String>();
379 emailAddresses.add( m.group());
381 return emailAddresses;
390 @Messages({
"ThunderbirdMboxFileIngestModule.addArtifact.indexError.message=Failed to index email message detected artifact for keyword search."})
391 private BlackboardArtifact
addArtifact(EmailMessage email, AbstractFile abstractFile) {
392 BlackboardArtifact bbart = null;
393 List<BlackboardAttribute> bbattributes =
new ArrayList<>();
394 String to = email.getRecipients();
395 String cc = email.getCc();
396 String bcc = email.getBcc();
397 String from = email.getSender();
398 long dateL = email.getSentDate();
399 String headers = email.getHeaders();
400 String body = email.getTextBody();
401 String bodyHTML = email.getHtmlBody();
402 String rtf = email.getRtfBody();
403 String subject = email.getSubject();
404 long id = email.getId();
405 String localPath = email.getLocalPath();
407 List<String> senderAddressList =
new ArrayList<>();
408 String senderAddress;
411 AccountFileInstance senderAccountInstance = null;
412 if (senderAddressList.size() == 1) {
413 senderAddress = senderAddressList.get(0);
417 catch(TskCoreException ex) {
418 logger.log(Level.WARNING,
"Failed to create account for email address " + senderAddress, ex);
422 logger.log(Level.WARNING,
"Failed to find sender address, from = "+ from);
425 List<String> recipientAddresses =
new ArrayList<>();
430 List<AccountFileInstance> recipientAccountInstances =
new ArrayList<>();
431 recipientAddresses.forEach((addr) -> {
433 AccountFileInstance recipientAccountInstance =
436 recipientAccountInstances.add(recipientAccountInstance);
438 catch(TskCoreException ex) {
439 logger.log(Level.WARNING,
"Failed to create account for email address " + addr, ex);
453 addEmailAttribute(((
id < 0L) ? NbBundle.getMessage(
this.getClass(),
"ThunderbirdMboxFileIngestModule.notAvail") : String.valueOf(
id)),
454 ATTRIBUTE_TYPE.TSK_MSG_ID, bbattributes);
457 ATTRIBUTE_TYPE.TSK_PATH, bbattributes);
460 addEmailAttribute(bodyHTML, ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_HTML, bbattributes);
466 bbart = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG);
467 bbart.addAttributes(bbattributes);
470 Case.
getCurrentCase().
getSleuthkitCase().getCommunicationsManager().addRelationships(senderAccountInstance, recipientAccountInstances, bbart,Relationship.Type.MESSAGE, dateL);
476 logger.log(Level.SEVERE,
"Unable to index blackboard artifact " + bbart.getArtifactID(), ex);
479 }
catch (TskCoreException | TskDataException ex) {
480 logger.log(Level.WARNING, null, ex);
486 private void addEmailAttribute(String stringVal, ATTRIBUTE_TYPE attrType, Collection<BlackboardAttribute> bbattributes) {
487 if (stringVal.isEmpty() ==
false) {
491 private void addEmailAttribute(
long longVal, ATTRIBUTE_TYPE attrType, Collection<BlackboardAttribute> bbattributes) {
497 void postErrorMessage(String subj, String details) {
502 IngestServices getServices() {
String getModuleOutputDirectoryRelativePath()
Set< String > findEmailAddresess(String input)
static final Logger logger
FileManager getFileManager()
String getTempDirectory()
static IngestMessage createErrorMessage(String source, String subject, String detailsHtml)
void addEmailAttribute(String stringVal, ATTRIBUTE_TYPE attrType, Collection< BlackboardAttribute > bbattributes)
BlackboardArtifact addArtifact(EmailMessage email, AbstractFile abstractFile)
static< T > long writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, Future< T > worker, boolean source)
synchronized DerivedFile addDerivedFile(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime, boolean isFile, Content parentObj, String rederiveDetails, String toolName, String toolVersion, String otherDetails, TskData.EncodingType encodingType)
void addEmailAttribute(long longVal, ATTRIBUTE_TYPE attrType, Collection< BlackboardAttribute > bbattributes)
ProcessResult processMBox(AbstractFile abstractFile)
static final int DISK_FREE_SPACE_UNKNOWN
void processEmails(List< EmailMessage > emails, AbstractFile abstractFile)
void addFilesToJob(List< AbstractFile > files)
static String getModuleOutputPath()
void postMessage(final IngestMessage message)
void fireModuleDataEvent(ModuleDataEvent moduleDataEvent)
ProcessResult process(AbstractFile abstractFile)
SleuthkitCase getSleuthkitCase()
String getModuleDirectory()
ProcessResult processPst(AbstractFile abstractFile)
void startUp(IngestJobContext context)
Blackboard getBlackboard()
void fireModuleContentEvent(ModuleContentEvent moduleContentEvent)
static void error(String title, String message)
static String getRelModuleOutputPath()
synchronized void indexArtifact(BlackboardArtifact artifact)
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
List< AbstractFile > handleAttachments(List< EmailMessage.Attachment > attachments, AbstractFile abstractFile, BlackboardArtifact messageArtifact)
static String getTempPath()
static synchronized IngestServices getInstance()