Skip to content

Instantly share code, notes, and snippets.

@mailme-gx
Forked from targzeta/eml2maildir.sh
Last active June 4, 2023 14:16
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save mailme-gx/cfd187033fbf201018a8 to your computer and use it in GitHub Desktop.
Save mailme-gx/cfd187033fbf201018a8 to your computer and use it in GitHub Desktop.
Traslates .eml file to maildir format.
#!/bin/bash
# Copyright (C) 2015
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Traslates .eml file to maildir format.
# originally forked from https://gist.github.com/targzeta/7137182 by "Emanuele Tomasi <targzeta@gmail.com>"
# latest version https://gist.github.com/mailme-gx/cfd187033fbf201018a8 by "GX"
# -h help
# Changelog:
# 2015/07/17
# Removed fromdos command
# Quoted filename to allow for spaces
# Change owner and group of file
# If source is a directory import all files in directory
# If no destination is specified use ./new as destination
# 2015/07/17
# find command use . not * to avoid "Argument list too long"
# TODO/NOTES
# cp command fails if a file ends with a trailing space i.e. cp "this file " "that_file"
# date command shows errors when parsing dates, this is not too much of a concrern as our email app parsers the date from the email header not file timestamp
SCRIPT_NAME=${0##*/}
SCRIPT_AUTHOR="GX"
USER=vmail
GROUP=vmail
#############
# FUNCTIONS #
#############
function _exit
{
echo -e "${SCRIPT_NAME}: ${1}"
exit $2
}
function _help
{
cat <<EOF
Use: ${SCRIPT_NAME} [option]... <source file or directory> [destination directory]
Translates a .eml file to a maildir filename. For setting hostname it uses
HOST environment variable or, if it isn't setted, HOSTNAME.
If no destination directory is specified the default name is new/ directory.
Options:
-c Setting the filename for a cur/ directory. You can set your flag by
setting the FLAG environment variable. Default FLAG is 'S'.
-d Dovecot extension. Sets the 'W' option.
-h Display this help and exit.
by ${SCRIPT_AUTHOR}"
EOF
}
function _check_extern_programs
{
local error=0
local string_error
if ! which which >&/dev/null
then
error=1
string_error="/usr/bin/which : command not founds.\n";
else
for progr in $@
do
if ! which $progr >& /dev/null
then
error=1
string_error=${string_error}"${progr} : command not founds.\n"
fi
done
fi
if (( $error ))
then
_exit "You need to install these commands:\n$string_error" 1
fi
}
function rename_file {
_TMPFILE=$(mktemp)
[ -z ${_TMPFILE} ] && exit 1
cp "$file" $_TMPFILE
_HOST=${HOST:-$HOSTNAME}
_RANDOM=$(</dev/urandom tr -cd '[:digit:]' | head -c 6)
_DATE=$(sed -n '/^Date:/{s/Date: //;p;q}' "$file")
_TIMESTAMP=$(date --date="$_DATE" '+%s')
_SIZE=$(stat $_TMPFILE --printf='%s')
_FILENAME="${_TIMESTAMP}.P${_RANDOM}Q2.${_HOST},S=${_SIZE}"
if (( $OPT_D == 1 ))
then
_WSIZE=$(stat "$file" --printf='%s')
_FILENAME+=",W=${_WSIZE}"
fi
if (( $OPT_C == 1 ))
then
_FLAG=${FLAG:-S}
_FILENAME+=":2,${_FLAG}"
fi
_OUTPUT_FILE=${destdir}/${_FILENAME}
mv $_TMPFILE "$_OUTPUT_FILE"
touch --date="${_DATE}" "$_OUTPUT_FILE"
chown $USER:$GROUP "$_OUTPUT_FILE"
}
##########
# CHECKS #
##########
enable getopts echo exit
IFS=$'\n\t '
OPT_C=0
OPT_D=0
while getopts :hcd opzione
do
case $opzione in
c) OPT_C=1;;
d) OPT_D=1;;
h) _help; exit;;
?) _exit "-${OPTARG} : not valid argument." 1;;
esac
done
while (( $OPTIND != 1 ))
do
shift
let --OPTIND
done
[ -z "$1" ] && _exit "missing argument. "\
"${SCRIPT_NAME} -h for help." 1
_check_extern_programs date head mktemp stat touch
########
# MAIN #
########
file_or_dir="$1"
destdir="$2"
[ -z "$destdir" ] && destdir="./new"
if [ ! -d "$destdir" ]
then
mkdir "$destdir"
chown $USER:$GROUP "$destdir"
fi
if [ -d "$file_or_dir" ]
then
find ${file_or_dir}/. -maxdepth 1 -type f | while read file; do
rename_file
done
else
file=$file_or_dir
rename_file
fi
#EOF
@lmanul
Copy link

lmanul commented Aug 2, 2021

I am not sure how to send a pull request for a gist (is that even possible), but I think the word "setted" should be "set" (English irregular verbs >,< ).

@lmanul
Copy link

lmanul commented Aug 2, 2021

Also, what is the purpose of setting the user and group to vmail / vmail ? Is it expected that this user would exist? It doesn't exist on my system. I changed both to $USER .

@mailme-gx
Copy link
Author

I am not sure how to send a pull request for a gist (is that even possible), but I think the word "setted" should be "set" (English irregular verbs >,< ).

Thanks Imanul, Yes this a Type

@mailme-gx
Copy link
Author

Also, what is the purpose of setting the user and group to vmail / vmail ? Is it expected that this user would exist? It doesn't exist on my system. I changed both to $USER .

The vmail user group is used when a setup is done with postfix and dovecot on a debian system. file permissions need to be set to that user.

You are using $USER will set permissions of the user running the script which might not be ideal. But if it works for you fine :)

@lmanul
Copy link

lmanul commented Aug 2, 2021

That makes sense! Sorry for the noise :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment