-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathemail.sh
153 lines (134 loc) · 4.92 KB
/
email.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/env bash
#
# parse_email.sh - A simple yet high-quality Bash script to parse a raw email file.
#
# Usage:
# parse_email.sh <email_file>
#
# Description:
# This script extracts the "From", "To", "Subject", and "Date" headers
# from a raw email file, then prints them along with the message body.
# The body is assumed to begin after the first blank line.
#
# Note:
# Real-world email parsing can be significantly more complex than this
# script demonstrates. For complex MIME, encodings, or multi-line headers,
# consider a dedicated parser.
###############################################################################
# Bash Strict Mode
###############################################################################
set -euo pipefail # Exit on error, undefined variable, or failed pipe
IFS=$'\n\t' # Safe Internal Field Separator
###############################################################################
# Global Constants
###############################################################################
readonly SCRIPT_NAME="${0##*/}"
###############################################################################
# Functions
###############################################################################
# ------------------------------------------------------------------------------
# usage()
# Display usage message and exit.
# ------------------------------------------------------------------------------
usage() {
cat <<EOF
Usage:
$SCRIPT_NAME <email_file>
Description:
Parse a raw email file and extract the "From", "To", "Subject", "Date",
and body. The body is assumed to begin after the first blank line.
Example:
$SCRIPT_NAME example.eml
EOF
exit 1
}
# ------------------------------------------------------------------------------
# check_requirements()
# Verify that necessary command-line tools are available.
# ------------------------------------------------------------------------------
check_requirements() {
local -a required_commands=("grep" "awk" "sed")
for cmd in "${required_commands[@]}"; do
if ! command -v "$cmd" &>/dev/null; then
echo "Error: '$cmd' command not found. Please install it." >&2
exit 1
fi
done
}
# ------------------------------------------------------------------------------
# parse_headers()
# Extract the primary headers: From, To, Subject, and Date.
# Arguments:
# 1. The path to the email file
# Outputs:
# Global variables: HEADER_FROM, HEADER_TO, HEADER_SUBJECT, HEADER_DATE
# ------------------------------------------------------------------------------
parse_headers() {
local email_file="$1"
HEADER_FROM="$(grep -m 1 '^From:' "$email_file" || true)"
HEADER_TO="$(grep -m 1 '^To:' "$email_file" || true)"
HEADER_SUBJECT="$(grep -m 1 '^Subject:' "$email_file" || true)"
HEADER_DATE="$(grep -m 1 '^Date:' "$email_file" || true)"
# Remove the field label and leading spaces
HEADER_FROM="${HEADER_FROM#From:}"
HEADER_TO="${HEADER_TO#To:}"
HEADER_SUBJECT="${HEADER_SUBJECT#Subject:}"
HEADER_DATE="${HEADER_DATE#Date:}"
# Trim leading whitespace
HEADER_FROM="$(echo "$HEADER_FROM" | sed 's/^[[:space:]]*//')"
HEADER_TO="$(echo "$HEADER_TO" | sed 's/^[[:space:]]*//')"
HEADER_SUBJECT="$(echo "$HEADER_SUBJECT" | sed 's/^[[:space:]]*//')"
HEADER_DATE="$(echo "$HEADER_DATE" | sed 's/^[[:space:]]*//')"
}
# ------------------------------------------------------------------------------
# parse_body()
# Extract the body of the email (all lines after the first blank line).
# Arguments:
# 1. The path to the email file
# Outputs:
# BODY_CONTENT
# ------------------------------------------------------------------------------
parse_body() {
local email_file="$1"
BODY_CONTENT="$(
awk '
BEGIN { in_body = 0 }
/^[[:space:]]*$/ { in_body = 1; next }
{ if (in_body == 1) print }
' "$email_file"
)"
}
# ------------------------------------------------------------------------------
# main()
# Main function coordinating the parsing and output.
# ------------------------------------------------------------------------------
main() {
# Check arguments
if [[ $# -ne 1 ]]; then
usage
fi
local email_file="$1"
# Validate the email file
if [[ ! -f "$email_file" ]]; then
echo "Error: File '$email_file' not found or not a regular file." >&2
exit 1
fi
# Ensure required tools are installed
check_requirements
# Parse the email
parse_headers "$email_file"
parse_body "$email_file"
# Print results
echo "From: ${HEADER_FROM:-"(Not found)"}"
echo "To: ${HEADER_TO:-"(Not found)"}"
echo "Subject: ${HEADER_SUBJECT:-"(Not found)"}"
echo "Date: ${HEADER_DATE:-"(Not found)"}"
echo
echo "Body:"
echo "------"
echo "${BODY_CONTENT:-"(No body found)"}"
}
###############################################################################
# Entry Point
###############################################################################
main "$@"