• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

Text aus Email-Datei extrahieren via command-line

abgdf

Guru
OsunSeyi schrieb:
Ich denke an `cat message | mail2text > message.txt`.
Code:
Content-Type: text/plain;
 charset=utf-8
Content-Transfer-Encoding: base64

U2VociBnZWVocnRlciBIZXJyIEJyw7Z0amUsDQoNCnZpZWxlbiBEYW5rIGbDvHIgSWhyZSBOYWNo
cmljaHQuIERlciBWb3JnYW5nIGlzdCBmw7xyIGRhcyBHZW5lcmFsa29uc3VsYXQgYWJnZXNjaGxv
c3Nlbi4gRGllIGVudHNjaGVpZHVuZ3NyZWxldmFudGVuI

Da bin ich mit meinem Latein am Ende![/code]
Ich aber (noch) nicht. ;) Probier' mal dieses als "mail2text.py" und also "cat message | mail2text.py":
Code:
#!/usr/bin/python
# coding: utf-8

# mail2text.py

import email
import email.utils
import base64
import sys

lines = sys.stdin.readlines()
l = []
for i in lines:
    l.append(i.rstrip("\n"))
lines = l

messages = []
mail = email.message_from_string("\n".join(lines))
for part in mail.walk():
    if part.get_content_type() == 'text/plain':
        payload = part.get_payload()
        enc = part['Content-Transfer-Encoding']
        if enc == 'base64':
            payload += "+++"
            payload = base64.b64decode(payload)
            messages.append(payload)
        else:
            messages.append(payload)

for i in messages:
    print i
Schöne Grüße an Herrn Br.... . ;)
 
OP
OsunSeyi

OsunSeyi

Hacker
@ josef-wien

Danke, ich werd's mir zu Herzen nehmen und mehr über die Bash lernen. Allerdings ist möglicherweise Hopfen und Malz verloren, denn meine Scripte werden immer "hausbackener" je länger das geht. :eek:ps:

https://www.jan-trippler.de/de/script_tipps/tuning.html

@ abgdf:

Vielen Dank, arbeitet soweit bestens!
Unglaublich, wie schön kurz so etwas sein kann...

Auf jeden Fall sind die Anhänge raus und den Rest kann ich selber in ein brauchbares Ergebnis überführen. Was allerdings nicht klappt, ist die Konvertierung von base64:

Code:
Traceback (most recent call last):
  File "/home/tom/BIN/TextTools/mail2text", line 25, in <module>
    payload = base64.b64decode(payload)
  File "/usr/lib/python2.7/base64.py", line 78, in b64decode
    raise TypeError(msg)
TypeError: Incorrect padding

Wenn ich den Code in eine extra Datei kopiere, klappt das Konverieren mit
"openssl enc -d -base64 -in file" aber durchaus!

Es wäre natürlich viel einfacher, wenn's direkt ginge.

Ps: es gibt dazu aber etwas im Netz:
https://frageit.de/questions/41538884/python-base64decode-error-between-strings
Grauenhafte Übersetzung :fies:

Ich habe in gandenloser Unwissenheit und Einfalt einfach mal ein und auch mehrere " =" hinzugefügt, was allerdings nichts am Ergebnis geändert hat...

Pps:
https://www.python-forum.de/viewtopic.php?t=23650
https://im-coder.com/wie-dekodiert-man-base64-url-in-python.html (letzter Beitrag)
Kann man nicht zur Not auch externe Programme mit Python aufrufen und 'openssl' die Konvertierung vornehmen lassen?
 

abgdf

Guru
OsunSeyi schrieb:
Was allerdings nicht klappt, ist die Konvertierung von base64
Code:
TypeError: Incorrect padding

Wenn ich den Code in eine extra Datei kopiere, klappt das Konverieren mit
"openssl enc -d -base64 -in file" aber durchaus!

Es wäre natürlich viel einfacher, wenn's direkt ginge.
Laut diesem:
https://gist.github.com/perrygeo/ee7c65bb1541ff6ac770

liegt "Incorrect Padding" daran, daß base64 eine bestimmte Anzahl von Zeichen voraussetzt (ein Vielfaches von 4 oder so), die der String so nicht hat. Einfache Lösung: Ein paar geeignete Zeichen anfügen. In dem Dokument ist es "=". Das ging bei mir nicht. Mit "+" ging es. Deshalb hatte ich in meinem Skript die Zeile:
Code:
payload += "+++"
Die fügt drei Pluszeichen an. Kann sein, daß es bei Dir mit "=" geht, dann wäre es stattdessen:
Code:
payload += "==="
OsunSeyi schrieb:
Kann man nicht zur Not auch externe Programme mit Python aufrufen und 'openssl' die Konvertierung vornehmen lassen?
Sicherlich. Ein system-Call ginge so:
Code:
import os
os.system("your_program")
 
OP
OsunSeyi

OsunSeyi

Hacker
Leider kann das Phyton-Script auch nicht reinen Html-Mails umgehen..
Da liegt der Hase also wieder im Pfeffer...

Code:
Return-Path: <anbieter-xc1p3f839jxmh@mail.ebay-kleinanzeigen.de>
Received:
Received:
Received:
DKIM-Signature:
Received:
Received:
Subject:
Content-Type: text/html;charset=UTF-8
Date: Mon, 11 Mar 2019 12:27:10 +0100 (CET)
Content-Transfer-Encoding: 7bit
X-Comaas-Tenant:
Message-ID:
To:
X-TOI-SPAM:
X-TOI-VIRUSSCAN:
X-TOI-MSGID:
X-ENVELOPE-TO:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
    <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1">
</head>
<body vlink="#001e9b" alink="#001e9b" link="#001e9b" bgcolor="#ffffff">
        ---TEXT---
</body>
</html>
 

abgdf

Guru
Locker bleiben:
Code:
#!/usr/bin/python
# coding: utf-8

# mail2text.py

import email
import email.utils
import base64
import sys
from bs4 import BeautifulSoup


lines = sys.stdin.readlines()
l = []
for i in lines:
    l.append(i.rstrip("\n"))
lines = l

messages = []
mail = email.message_from_string("\n".join(lines))
for part in mail.walk():
    if part.get_content_type() == 'text/plain':
        payload = part.get_payload()
        enc = part['Content-Transfer-Encoding']
        if enc == 'base64':
            payload += "+++"
            payload = base64.b64decode(payload)
            messages.append(payload)
        else:
            messages.append(payload)
    if part.get_content_type() == 'text/html':
        payload = part.get_payload()
        messages.append(payload)
        soup = BeautifulSoup("\n".join(messages), 'html.parser')
        text = soup.get_text()
        messages = text.split("\n")

for i in messages:
    print i
Modul "BeautifulSoup"/bs4 wird benötigt. Bei mir (OpenSuSE 13.1) gibt es Pakete in der Distribution (python-beautifulsoup...rpm, python-beautifulsoup4...rpm). Bei Dir bestimmt auch.
 
OP
OsunSeyi

OsunSeyi

Hacker
:thumbs:

Das war's...
Jetzt bleibt noch die Frage nach den Base64 codierten Mails.
Wenn ich also nicht die Zeichen zählen will (aber ich kann kein Phyton), bliebe als Möglichkeit:

Code:
import os
os.system(/usr/bin/openssl)

Aber dann geht's ja weiter, nämlich wie die Optionen an openssl übergeben...
Code:
openssl enc -d -base64 -in file

Im Script finde ich:
Code:
        if enc == 'base64':
            payload += "+++"
            payload = base64.b64decode(payload)
            messages.append(payload)

:???: :mute:
In besagtem Link https://im-coder.com/wie-dekodiert-man-base64-url-in-python.html (letzter Beitrag) heißt es so schön:

Überraschend, aber die derzeit akzeptierte Antwort ist nicht ganz richtig.
Wie einigen anderen Antworten gesagt, es ist etwas genannt base64url Codierung, und es ist ein Teil der RFC7515.

Im Grunde, die Sie ersetzt haben '+' und '/' chars durch '-' und '_' sind; und zusätzlich entfernt alle nachgestellten '=' Zeichen, da kann man immer sagen, wie viele chars du bist fehlt, nur durch die Betrachtung der kodierten string der Länge.

Hier ein illustratives Beispiel aus RFC7515 in C#:
...


Also, angesichts der grottigen Übersetzung rate ich mal, daß Base64 mit nicht stimmiger Anzahl Zeichen (falschem Bounding) trotzdem korrekter Bestandteil von RFC7515 sein kann? Es kommt einem ja auch krude vor, immer erst die Anzahl Zeichen vom Base64-Teil zählen zu müssen, um dann ggF noch Zeichen hinzuzufügen...
 

abgdf

Guru
OsunSeyi schrieb:
Also, angesichts der grottigen Übersetzung rate ich mal, daß Base64 mit nicht stimmiger Anzahl Zeichen (falschem Bounding) trotzdem korrekter Bestandteil von RFC7515 sein kann? Es kommt einem ja auch krude vor, immer erst die Anzahl Zeichen vom Base64-Teil zählen zu müssen, um dann ggF noch Zeichen hinzuzufügen...
In dem anderen Link hieß es, man bräuchte immer was, das durch 4 teilbar sei. Wenn man 3 Zeichen hinzufüge, sei man auf der sicheren Seite. Sollten es zu viele Zeichen sein, würden sie abgeschnitten.
Fragt sich nur, welche Zeichen. "=" wurde vorgeschlagen, aber bei mir ging nur "+". "+" ging bei Dir nicht. Wie gesagt, ich würde mal "=" versuchen. Es ist immer schwer, was zu einem Fehler zu sagen, der bei einem selbst nicht auftritt (bei mir ging "+" ja).
 
OP
OsunSeyi

OsunSeyi

Hacker
Nein, ging bei mir leider nicht.
Ich probiere es nochmal per bash-script, die verschiedenen Formate zu erkennen und herauszulösen..
 

abgdf

Guru
Sicher, man kann auch genausogut den bash-Befehl "base64" aus den coreutils verwenden (mit der Option "-d").
Vielleicht kann es ja auch helfen, daß das Python-Skript erkennt, ob die Nachricht base64-codiert ist oder nicht. Hab's jetzt gerade mal so gebaut, daß es nicht selbst decodiert, aber am Anfang ggf. eine Zeile mit dem Inhalt "base64encoded" ausgibt.
Dann kannst Du das mit dem bash-Befehl weiter verarbeiten:
Code:
#!/usr/bin/python
# coding: utf-8

# mail2text.py

import email
import email.utils
import base64
import sys
from bs4 import BeautifulSoup

def checkBase64(part):
    enc = ""
    if part.has_key('Content-Transfer-Encoding'):
        enc = part['Content-Transfer-Encoding']
    if enc == 'base64':
        return "base64encoded"
    else:
        return ""

lines = sys.stdin.readlines()
l = []
for i in lines:
    l.append(i.rstrip("\n"))
lines = l

b64 = ""
messages = []
mail = email.message_from_string("\n".join(lines))

for part in mail.walk():

    if part.get_content_type() == 'text/plain':
        payload = part.get_payload()
        b64 = checkBase64(part)
        messages.append(payload)

    if part.get_content_type() == 'text/html':
        payload = part.get_payload()
        b64 = checkBase64(part)
        messages.append(payload)
        soup = BeautifulSoup("\n".join(messages), 'html.parser')
        text = soup.get_text()
        messages = text.split("\n")

if b64:
    print b64
for i in messages:
    print i
 

abgdf

Guru
Zusätzliches bash-Skript. Dann also "cat mail | mail2txt.py | noch_ein_bash_skript.sh" :roll: :
Code:
#!/bin/bash

decode=0
while read i
do
    if [ $i == "base64encoded" ]
    then
        decode=1
        continue
    fi
    if [ $decode -eq 1 ]
    then
        echo $i | base64 -d -
    else
        echo "$i"
    fi
done
Bei der Beispielmail funktioniert das bei mir (größtenteils, am Ende gibt's einen Fehler, aber da ist schon alles decodiert).
 
OP
OsunSeyi

OsunSeyi

Hacker
Ich hab das auf etwa 250 Mails getestet, das geht mit Claws-Mail recht gut, weil dort alle Mails als einzelne Dateien hinterlegt sind und ein "for...do...done" reicht, um zu testen.

Das obige Script läuft bei vielen Mails hier nicht zufriedenstellend (ich wünschte, es wäre anders...).

Habe selber etwas zusammengezimmert, was ziemlich grottig ist und auch nicht bei allen Mails saubere Ergebnisse bringt. Man kann die jeweilige Mail mit dem Seamonkey-Mail-Editor öffnen (direkt 'öffne Datei' im Menü). Da wird dann "jeder Mist" korrekt dargestellt!

Zu dem Script: Es geht davon aus, daß wenn im Header bereits eine 'Content-Type' Angabe ist, der Nachrichten-Teil zwischen Header und den Anhängen findet.

Wenn es eine Multipart-Message ist, findet sich der Content-Type im Body, und zwar in *fast, fast* allen Fällen Text/Plain vor Text/Html.

Nach dieser Methode wird der Nachrichten-Teil herausgelöst, Plain-Text wird vor Html bevorzugt. Betreffs der Codierung wird dann weitergesehen.

Wenn Ihr das Script testen wollt, werdet Ihr es anpassen müssen, es ist ziemlich hausbacken und benutzt zB zwei temporäre Dateien zum zwischenspeichern.
Meine Fähigkeiten sind halt begrenzt...

Die Farbangaben und das Verzeichniss "$SRC" kommen aus dem ". inc" am Anfang, das müsstet ihr sinnfällig ersetzen! Ich schicke das Script gleich mit, find ich persönlich nett.

Zum Konvertieren von "quoted-printable" benutze ich "hex2txt", das funktioniert hier besser als zB " python -m quopri -d", warum auch immer...

Zum Konvertieren von iso nach utf benutze ich "iconv -c -s -f ISO-8859-15 -t UTF-8 2>/dev/null" in einem Script namens "iso2utf".

Zum Konvertieren von Html "html2text" aus dem repository, das ist Python.
Zum Konvertieren von Base64 "base64 -d".

Für Form & Stil entschuldige ich mich hier vorsichtshalber schon mal... :( :-D

mail2txt:
Code:
#!/bin/sh
## mail2txt [file]
##	extrahiert den Text aus einer Email
#										01.03.2019
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
										     . inc
	FILE=$1
#	echo -e $hellrot$FILE$def

	 TMP=$SRC/tmp/mail2txt
	TMP0=$TMP/`echo $FILE | tr '/' '-'`_0.tmp
	TMP1=$TMP/`echo $FILE | tr '/' '-'`_1.tmp

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	UMBEKANNTES ZEICHEN AM DATEIENDE /////////////////////////////////////////////////
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	Es gibt offenbar Dateien mit einem im Editor nicht angezeigten Zeichen am
#	Zeilenende, was z.B. den Ausdruck "egrep '^$'" für eine Leerzeile verunmöglicht
#	und mit 'sed' entfernt werden muss:

	cat $FILE | sed 's|[[:space:]]\?$||g' > $TMP1
	FILE=$TMP1

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	ATTACHMENTS , BODY ///////////////////////////////////////////////////////////////
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	MIME='(application|image|audio|video)'

	BEGIN_ATTMENTS=`egrep -in "Content-Type: $MIME"	$FILE	| tr '\n' ' ' | sed 's|:.*||g'`
	BEGIN_MAILBODY=`egrep -n "^$" $FILE			| tr '\n' ' ' | sed 's|:.*||g'`

	if [ -z "$BEGIN_ATTMENTS" ] ; then BEGIN_ATTMENTS='$' ; fi

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	CONTENT-ANGABE IM HEADER  ////////////////////////////////////////////////////////
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	HEAD_TYPE_TEXT=`sed -n '1,/^$/p' $FILE | egrep -in 'Content-Type: text/plain' | tr '\n' ' ' | sed 's|:.*||g'`
	HEAD_TYPE_HTML=`sed -n '1,/^$/p' $FILE | egrep -in 'Content-Type: text/html'  | tr '\n' ' ' | sed 's|:.*||g'`

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	CONTENT-ANGABE IM BODY  //////////////////////////////////////////////////////////
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	if [ -z "$HEAD_TYPE_TEXT" -a -z "$HEAD_TYPE_HTML" ] ; then

		BODY_TYPE_TEXT=`egrep -in 'Content-Type: text/plain' $FILE | tr '\n' ' ' | sed 's|:.*||g'`
		BODY_TYPE_HTML=`egrep -in 'Content-Type: text/html'  $FILE | tr '\n' ' ' | sed 's|:.*||g'`
	fi

#=========================================================================================
#/////	FEHLERSUCHE   ////////////////////////////////////////////////////////////////////
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
#	echo 'BEGIN_MAILBODY '$BEGIN_MAILBODY
#	echo 'BEGIN_ATTMENTS '$BEGIN_ATTMENTS
#	echo -e $hellrot'HEAD:'$def
#	echo 'HEAD_TYPE_TEXT '$HEAD_TYPE_TEXT
#	echo 'HEAD_TYPE_HTML '$HEAD_TYPE_HTML
#	echo -e $hellrot'BODY:'$def
#	echo 'BODY_TYPE_TEXT '$BODY_TYPE_TEXT
#	echo 'BODY_TYPE_HTML '$BODY_TYPE_HTML
#
#=========================================================================================
#/////	AUSWERTUNG NACH TMP  /////////////////////////////////////////////////////////////
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	if   [ -n "$HEAD_TYPE_TEXT" ] ; then

		sed -n "$BEGIN_MAILBODY,$BEGIN_ATTMENTS"p $FILE			> $TMP0

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	elif [ -n "$HEAD_TYPE_HTML" ] ; then

		TYPE_HTML='x'

		sed -n "$BEGIN_MAILBODY,$BEGIN_ATTMENTS"p $FILE			> $TMP0

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	elif [ -n "$BODY_TYPE_TEXT" ] ; then

		if [ -n "$BODY_TYPE_HTML" ] ; then BEGIN_ATTMENTS=$BODY_TYPE_HTML ; fi

		sed -n "$BEGIN_MAILBODY,$BEGIN_ATTMENTS"p $FILE			> $TMP0

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	elif [ -n "$BODY_TYPE_HTML" ] ; then

		TYPE_HTML='x'

		sed -n "$BEGIN_MAILBODY,$BEGIN_ATTMENTS"p $FILE			> $TMP0

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	else
		echo 'NO TEXT-CONTENT'						> $TMP0
	fi
#											cat $TMP0 ; rm $TMP/* ; exit
#=========================================================================================
#/////	BEARBEITEN  //////////////////////////////////////////////////////////////////////
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	UTF 8  ///////////////////////////////////////////////////////////////////////////
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	Es kann sein, daß dieser folgende Schritt überflüssig ist.
#	Ich weiss nicht, warum '< $TMP0 > $TMP1' nicht funktioniert.
#	...armes, missbrauchtes cat...

	TEST_ISO=`file $TMP0 | grep 'ISO'`

	if [ -n "$TEST_ISO" ] ; then

		cat $TMP0 | iso2utf 	> $TMP1
	else
		cat $TMP0 		> $TMP1
	fi

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	BOUNDINGS  ///////////////////////////////////////////////////////////////////////
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	Es wird davon ausgegangen, daß Boundings mit '--' anfangen, und danach alles
#	mögliche enthalten nur keine Leerzeichen. Sie *müssen* aber auch andere Zeichen
#	als '-' enthalten, darum das zweite 'grep'.
#	Es gibt auch Boundings mit '/', welches ersetzt werden muss!

	BOUNDINGS=`egrep '^\-\-[^[:space:]]{5,}' $TMP1 | grep '[0-9a-z]' | tr '/' '.'`

	for BOUNDING in $BOUNDINGS ; do sed -i "/$BOUNDING/d" $TMP1 ; done
#											echo $BOUNDINGS | tr ' ' '\n' ; exit
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	ERSETZUNGEN  /////////////////////////////////////////////////////////////////////
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	CONTENTS='(Type|Transfer|Disposition)'

	egrep -vi "^[[:space:]]*Content-$CONTENTS"  $TMP1 				|\
	egrep -vi 'boundary='								|\
	egrep -vi 'charset='								|\
	egrep -vi 'Mime-Version'							|\
	egrep -vi 'This is a multi-part message in MIME format'				|\
											 \
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	...ggF mehr hinzufügen!
#
#	Leerzeilen am Anfang und Ende:
#	http://sed.sourceforge.net/sed1line_de.html
											 \
	sed '/./,$!d'									|\
	sed '/^[[:space:]]*$/{:a;$d;N;/\n[[:space:]]*$/ba}' 				 \
											 \
									> $TMP0
#											cat $TMP0 ; exit
#=========================================================================================
#/////	ENCODING  ////////////////////////////////////////////////////////////////////////
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
#	Die hier verwendeten Suchmuster könnten ohne weiteres auch durch Auslesen
#	von "Content-Transfer-Encoding" ermittelt werden, sollten aber in der Praxis
#	funktionieren:
#
#	===========================================
#	Content-Transfer-Encoding: quoted-printable
#	===========================================

	TEST_HEX=`egrep '=[A-Za-z0-9]' $TMP0`
#											echo $TEST_HEX ; exit
#	=================================
#	Content-Transfer-Encoding: base64
#	=================================
#	http://www.zotteljedi.de/base64/

	TEST_BASE=`egrep -in '^[a-z0-9+/]{60,}[[:space:]]?$' $TMP0 | tr '\n' ' ' | sed 's|:.*||g'`

#											echo $TEST_BASE ; exit
	if   [ -n "$TEST_HEX"  ] ; then

		cat $TMP0 | hex2txt					> $TMP1

	elif [ -n "$TEST_BASE" ] ; then

#		~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#		Wenn *vor* dem Base64-Code noch anderer Text ist, kann nicht encodiert
#		werden. Darum werden alle Zeilen bis zu dem ersten Treffer von 'egrep'
#		in "$TEST_BASE" entfernt:
#		~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

		if [ "$TEST_BASE" -gt 1 ] ; then

			BASE=$(( $TEST_BASE - 1 ))
#											cat $TMP0 | sed "1,/$BASE/d" ; exit
			cat $TMP0 | sed "1,/$BASE/d" | base64 -d	> $TMP1

		else
			cat $TMP0 | base64 -d				> $TMP1
		fi

	else
		cat $TMP0						> $TMP1
	fi

#											cat $TMP1 ; exit
#	=======================
#	Content-Type: text/html
#	=======================

	if [ -n "$TYPE_HTML" ] ; then

		cat $TMP1 | html2text | sed 's|!\[\]()||g'		> $TMP0
	else
		cat $TMP1						> $TMP0
	fi

#=========================================================================================
#/////	ÜBERFLÜSSIGES ENTFERNEN //////////////////////////////////////////////////////////
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
#	Es gibt Ausgaben ohne abschließenden Zeilenumbruch:

	echo ''	>> $TMP0

	cat $TMP0									|\
											 \
#		mehr als zwei Leerzeilen am Stück:
											 \
		tr '\n' '^' | sed 's|\^^^\+|^|g'					|\
											 \
#		wiederum Zeilenumbrüche:
											 \
		sed 's|^\^\+||g' | sed 's|\^\+$||g' | tr '^' '\n'			|\
											 \
#		alle Links:
											 \
		egrep -v 'https?:'							|\
											 \
#		alle warum auch immer vorhandenen Html-Tags:
											 \
		sed 's|<[^>]\+>||g'


#	to be continued...
											echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'
rm $TMP/* ; exit
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FIN@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

hex2txt:
Code:
#!/bin/sh
## hex2txt
##	konvertiert hexadezimal kodierte Sonderzeichen in Emails in normale Zeichen um,
##	sowohl fuer ISO 8859 als auch UTF-8. Content-Transfer-Encoding: quoted-printable
#
#										23.03.2019
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
										     . inc
#  siehe:
#  www.gerhard-fobe.de/besondere-zeichen-wie-umlaute-in-mailheadern-und-mailinhalten/
#
#  Alle E-Mails müssen im Zeichensatz US-ASCII verfasst werden und zwar ohne
#  länderspezifische Erweiterungen durch Codepages, wo dann auch die Umlaute 
#  beinhaltet wären.
#
#  Somit müssen alle Umlaute und besondere Sprachzeichen in eine Hexadezimaldarstellung
#  umgewandelt werden. Dabei muss der Hexadezimaldarstellung ein "=" vorangestellt werden.
#  Somit wird bspw. ö zu =F6.
#
#  Doch aufgepasst:
#  Es muss die allgemeine Zeichenkodierung der E-Mail beachtet werden.
#
#  In deutsch finden dabei die Zeichenkodierungen ISO 8859 oder UTF-8.
#  In UTF-8 wäre ö das Zeichen U+00F6, welches hexadezimal dann =C3=B6 dargestellt würde.
#
#  www.utf8-zeichentabelle.de/unicode-utf8-table.pl
#  www.ude.de/internet/ansi-zeichen-in-e-mails.html
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#////	UTF8   ///////////////////////////////////////////////////////////////////////////
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	sed 's|=c3=84|Ä|gi'	|  sed 's|=c3=96|Ö|gi'      |  sed 's|=c3=9c|Ü|gi'	|\
	sed 's|=c3=a4|ä|gi'	|  sed 's|=c3=b6|ö|gi'      |  sed 's|=c3=bc|ü|gi'	|\
											 \
	sed 's|=c3=9f|ß|gi'	|  sed 's|=E2=80=A2|-|gi'   |  sed 's|=C2=A7|§|gi'	|\
											 \
	sed 's|=E2=80=9E|"|gi'	|  sed 's|=E2=80=9C|"|gi'   |  sed 's|=E2=82=AC|E|gi'   |\
											 \
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#////	ISO   ////////////////////////////////////////////////////////////////////////////
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
											 \
	sed 's|=C4|Ä|gi'	|  sed 's|=D6|Ö|gi'	    |  sed 's|=DC|Ü|gi'		|\
	sed 's|=E4|ä|gi'	|  sed 's|=F6|ö|gi'	    |  sed 's|=FC|ü|gi'		|\
											 \
	sed 's|=DF|ß|gi'	|  sed 's|=B4|-|gi'	    |  sed 's|=A7|§|gi'		|\
											 \
	sed 's|=93|"|gi'	|  sed 's|=94|"|gi'   					|\
											 \
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#////	WEITERES   ///////////////////////////////////////////////////////////////////////
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#  Kodierungen zum Zeilenumbruch sind kompliziert:
											 \
	tr '\n' '^'  | sed 's|=[[:space:]]*^||g' | tr '^' '\n' | sed 's|=20||g'		|\
											 \
#  alles oben nicht erkannte:
											 \
	sed 's|\(=\([A-Z0-9]\)\{2\}\)\{1,2\}| |gi'
#	sed 's|\(\(=\([A-Z0-9]\)\{2\}\)\{1,2\}\)|[\1]|gi'


#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FIN@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Konsole-Farben:
Code:
#! /bin/sh
## color [-show]
##	"echo -e $farbname .. $def"
##	stellt Konsolefarbe zur Verfuegung.
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
										   . help
# Def: die normale Textfarbe der verwendeten Konsole:

            def="\033[0m"
##
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
##	TEXT:
##	schwarz, grau, rot, hellrot, gruen, hellgruen, braun, gelb,
##	blau, hellblau, magenta, rosa, cyan, hellcyan, weiss, hellgrau

        schwarz="\033[00;30m"
           grau="\033[01;30m"
            rot="\033[00;31m"
        hellrot="\033[01;31m"
          gruen="\033[00;32m"
      hellgruen="\033[01;32m"
          braun="\033[00;33m"
           gelb="\033[01;33m"
           blau="\033[00;34m"
       hellblau="\033[01;34m"
        magenta="\033[00;35m"
           rosa="\033[01;35m"
           cyan="\033[00;36m"
       hellcyan="\033[01;36m"
          weiss="\033[00;37m"
       hellgrau="\033[01;37m"

##
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
##	HINTERGRUND:
##	BGschwarz, BGrot, BGgruen, BGgelb, BGblau, BGmagenta, BGcyan, BGhellgrau

     BGschwarz="\033[40m"
         BGrot="\033[41m"
       BGgruen="\033[42m"
        BGgelb="\033[43m"
        BGblau="\033[44m"
     BGmagenta="\033[45m"
        BGcyan="\033[46m"
    BGhellgrau="\033[47m"

#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#	SHOW:

if [ "$1" = '-show' ] ; then echo -e "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        $schwarz schwarz$def        $grau         grau	$def
            $rot rot	$def        $hellrot hellrot		$def
          $gruen gruen	$def        $hellgruen hellgruen	$def
          $braun braun	$def        $gelb gelb		$def
           $blau blau	$def        $hellblau hellblau	$def
        $magenta magenta$def        $rosa         rosa	$def
           $cyan cyan	$def        $hellcyan hellcyan	$def
          $weiss weiss	$def        $hellgrau hellgrau	$def

           $BGschwarz     $def  BGschwarz      $BGrot     $def  BGrot
           $BGgruen     $def  BGgruen        $BGgelb     $def  BGgelb
           $BGblau     $def  BGblau         $BGmagenta     $def  BGmagenta
           $BGcyan     $def  BGcyan         $BGhellgrau     $def  BGhellgrau
"
exit 0
fi

#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@FIN@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Ps: Wer ein korrektes Absendedatum möchte, kann das so bekommen:
Code:
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#/////	NAMENSGEBUNG  ////////////////////////////////////////////////////////////////////
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
#	Die Namensgebung der Dateien soll der Timestamp aus dem Absendedatum der Mail
#	sein. Dies scheint bei allen Emails gleich zu sein:
#
#			"Date: Tue, 22 Jul 2014 19:25:36 +0200"
#
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	Zunächst nur der mittlere Teil "22 Jul 2014 19:25:36", der sich offenbar direkt
#	in einen Timestamp konvertieren lässt. Wir nehmen nur Angaben aus dem Header:
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#											echo $1
		     EXPR='[0-9]\{1,2\} [A-Za-z]\{3\} [0-9]\{4\} [0-9:]\{8\}'

		BASE_DATE=`sed -n '1,/^$/p' $1 | egrep '^Date:' | sed "s|^.* \($EXPR\).*$|\1|g"`
	   BASE_TIMESTAMP=`date -d "$BASE_DATE" +%s`

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	Weiterhin interessiert der sogenannte Offset, der die Differenz zur Weltzeit
#	darstellt und berücksichtigt werden muss, soll die Reihenfolge korrekt werden.
#	Die Angabe ist +-Stunde Minute
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

		KORR_DATE=`sed -n '1,/^$/p' $1 | egrep '^Date:' | sed 's|^.*\([+-][0-9]\{4\}\).*$|\1|g' | egrep '[+-][0-9]{4}'`

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	In allen mir untergekommenen Mails ist die Stundenangabe einstellig, egal.
#	Mit einem leeren Operator lässt sich nicht rechnen, wenn er '-' ist,
#	wird das überschrieben:
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

		OPERATOR='+'
		OPERATOR=`echo $KORR_DATE | sed 's|\([+-]\)[0-9][0-9][0-9][0-9]|\1|g'`
		KORR_HRS=`echo $KORR_DATE | sed 's|[+-]\([0-9][0-9]\)[0-9][0-9]|\1|g' | sed 's|^0||g'`

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	Heraus kommt im obigen Beispiel "2" Stunden. Gibt es keine Offset-Angabe, bleibt
#	die Ausgabe leer, womit sich ebenfalls nicht rechnen lässt:
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

		if [ -z "$KORR_HRS" ] ; then KORR_HRS='0' ; fi

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	1h = 60x60 = 3600s:
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

		KORR_TIMESTAMP=$(( $KORR_HRS*3600 ))

#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#	Die Summe aus $BASE_TIMESTAMP und $KORR_TIMESTAMP sollte ein vergleichbares
#	Ergebnis bringen und wird als Dateiname verwendet:
#	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

		NAME=$(( $BASE_TIMESTAMP$OPERATOR$KORR_TIMESTAMP ))
#											echo $NAME ; exit
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
Oben