# Automatically save  e-mail attachments to disk as Cron job



## swebichon (Jan 17, 2013)

I need a way to save .XML attachments to disk from e-mails that have been sent to a certain e-mail account (POP3). This needs to be done as a "background" job (e.g. cron) and fully command-line based (no GUIs). Does anyone here have a clue on how to fix this? Preferably using some software available as a port/package.

Thanks in advance.


----------



## fonz (Jan 17, 2013)

It's probably possible to write a Perl or Python script for that. But I'd call it from mail/procmail rather than cron(8).

Fonz


----------



## wblock@ (Jan 17, 2013)

mail/procmail is old and crusty.  mail/maildrop is the new shiny version.  See Switching From procmail To maildrop.


----------



## fonz (Jan 17, 2013)

wblock@ said:
			
		

> mail/procmail is old and crusty.  mail/maildrop is the new shiny version.  See Switching From procmail To maildrop.


I'll save that for future perusal. Thanks pending 

@swebichon: Here's a simple sample Perl script that might help you get started. It obviously requires Perl and it also needs mail/p5-MIME-Tools. You may want to add a few sanity checks (e.g. does the target directory exist and is it writable?) but I'll leave that as an exercise. Don't forget to adjust the [red]red[/red] line to your liking; it determines where the XML files are saved.

```
#!/usr/bin/perl

use MIME::Parser;

[red]my $directory="/tmp";[/red]
my $parser=new MIME::Parser;
$parser->output_to_core(1);
$entity=$parser->parse(\*STDIN);
foreach($entity->parts())
{
  my $type=$_->mime_type;
  my $filename=$_->head->recommended_filename;
  my $path="";
  if($type=~q@application/xml@)
  {
    if($fh=$_->open("r"))
    {
      $path=$directory."/".$filename;
      open(FH,">$path");
      while(defined($_=$fh->getline))
      {
        print FH $_;
      }
      close(FH);
      $fh->close;
    }
  }
}
```
You can test it by saving an email to a file (say message.txt) and feeding it to the script (say you called it /path/to/script.pl) as follows: `% /path/to/script.pl < message.txt`

If you use mail/procmail, you can use the following recipe:

```
:0c:
| /path/to/script.pl
```
If you use another mail filter or decide to use cron(8) after all, you'll probably know what to do.

Hope this helps,

Fonz


----------



## swebichon (Jan 22, 2013)

Thanks for your suggestions.

I solved the problem but not in FreeBSD, but instead on an OSX server I have running. I simply installed an account in the apple's mail application for retreiving e-mail from the account. Then I added a rule in apple's mail app that filters out all e-mails from a certain e-mail address AND that has at least one attachment with a filename that ends with ".xml". For these e-mails I have assigned two actions:
1) move each such mail to a separate folder in the mail program, then
2) execute an apple script that saves the attachments to a pre-specified folder on the harddrive.

Once the apple script has saved the attachment, it calls a shell script that does all the magic on the files in the harddrive.

The apple script goes as follows:


```
using terms from application "Mail"
	on perform mail action with messages theMessages for rule theRule
		-- The folder to save the attachments in (must already exist)
		
		
		-- Save in a sub-folder based on the name of the rule in Mail
		
		set subFolder to name of theRule
		tell application "Finder"
			set attachmentsFolder to ((path to home folder as text) & "sub-dir-in-the-home-folder:sub-sub-folder:sub-sub-sub-folder") as text
			if not (exists folder subFolder of folder attachmentsFolder) then
				make new folder at attachmentsFolder with properties {name:subFolder}
			end if
		end tell
		tell application "Mail"
			
			repeat with eachMessage in theMessages
				
				--set {year:y, month:m, day:d, hours:h, minutes:min} to eachMessage's date sent
				--set timeStamp to ("" & y & "-" & my pad(m as integer) & "-" & my pad(d) & "-" & my pad(h) & "-" & my pad(min))
				
				try
					-- Save the attachment
					repeat with theAttachment in eachMessage's mail attachments
						
						set originalName to name of theAttachment
						--set savePath to attachmentsFolder & ":" & subFolder & ":" & timeStamp & " " & originalName
						set savePath to attachmentsFolder & ":" & subFolder & ":" & originalName
						try
							save theAttachment in file (savePath)
						end try
					end repeat
					
					--display dialog subFolder
				end try
			end repeat
			
		end tell
		--display dialog attachmentsFolder
		do shell script "/absolute-path-to-shell-script.sh"
		
	end perform mail action with messages
end using terms from
```


----------

