Skip to content

Commit a4e7da4

Browse files
committed
store subject and content.
override tzdata package. Add subject and content columns to emails table.
1 parent 8bdded8 commit a4e7da4

File tree

8 files changed

+89
-8
lines changed

8 files changed

+89
-8
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,5 @@ temp_mail-*.tar
3434
*.iml
3535

3636
all_files_contents.txt
37-
concat-files.sh
37+
concat-files.sh
38+
.aider*

lib/temp_mail/email.ex

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ defmodule TempMail.Email do
66
field :from, :string
77
field :to, {:array, :string}
88
field :data, :string
9+
field :subject, :string
10+
field :content, :string
911
field :received_at, :integer
1012

1113
timestamps()

lib/temp_mail/email_store.ex

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ defmodule TempMail.EmailStore do
33
alias TempMail.{Repo, Email}
44
require Logger
55

6-
def store_email(from, to, data) do
6+
def store_email(from, to, data, subject, content) do
77
Logger.info("Storing email from #{from} to #{Enum.join(to, ", ")}")
88

99
email = %Email{
1010
from: from,
1111
to: to,
1212
data: data,
13-
received_at: :os.system_time(:seconds)
13+
subject: subject,
14+
content: content,
15+
received_at: :os.system_time(:seconds),
1416
}
1517

1618
Repo.insert(email)

lib/temp_mail/smtp_server.ex

+66-2
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,73 @@ defmodule TempMail.SMTPServer do
3535

3636
def handle_DATA(from, to, data, state) do
3737
Logger.info("handle_DATA, Received email from #{from} to #{Enum.join(to, ", ")}")
38-
TempMail.EmailStore.store_email(from, to, data)
39-
{:ok, "250 ok", state}
38+
39+
case :mimemail.decode(data) do
40+
{"text", subtype, headers, params, body} ->
41+
# Simple text email without attachments
42+
email_content = %{
43+
from: from,
44+
to: to,
45+
subject: get_subject({nil, nil, headers, params, nil}),
46+
body: body,
47+
attachments: []
48+
}
49+
Logger.debug("email_content: #{inspect(email_content)}")
50+
TempMail.EmailStore.store_email(from, to, data, email_content.subject, email_content.body)
51+
{:ok, "250 ok", state}
52+
53+
{_type, _subtype, headers, params, parts} = email ->
54+
# Email with potential attachments
55+
attachments = extract_attachments(email)
56+
email_content = %{
57+
from: from,
58+
to: to,
59+
subject: get_subject(email),
60+
body: get_text_body(email),
61+
attachments: attachments
62+
}
63+
{:ok, "250 ok", state}
64+
65+
error ->
66+
{:error, "554 Error: Unable to process email", state}
67+
end
68+
end
69+
70+
defp extract_attachments({_type, _subtype, _headers, _params, parts}) when is_list(parts) do
71+
Enum.flat_map(parts, fn
72+
{"text", _subtype, _headers, _params, _content} ->
73+
[]
74+
{_type, _subtype, headers, params, content} ->
75+
case :proplists.get_value("Content-Disposition", headers) do
76+
disposition when is_binary(disposition) ->
77+
if String.starts_with?(disposition, "attachment") do
78+
[%{
79+
filename: :proplists.get_value("filename", params),
80+
content: Base.encode64(content),
81+
content_type: :proplists.get_value("Content-Type", headers)
82+
}]
83+
else
84+
[]
85+
end
86+
_ ->
87+
[]
88+
end
89+
end)
90+
end
91+
defp extract_attachments(_), do: []
92+
93+
defp get_subject({_type, _subtype, headers, _params, _parts}) do
94+
:proplists.get_value("Subject", headers, "")
95+
end
96+
97+
defp get_text_body({_type, _subtype, _headers, _params, parts}) when is_list(parts) do
98+
Enum.find_value(parts, fn
99+
{"text", "plain", _headers, _params, content} -> content
100+
_ -> nil
101+
end) || ""
40102
end
103+
defp get_text_body({"text", "plain", _headers, _params, content}), do: content
104+
defp get_text_body(_), do: ""
41105

42106
def handle_RSET(state) do
43107
{:ok, state}

lib/temp_mail/templates/emails.html.eex

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
<li>
1313
<strong>From:</strong> <%= email.from %><br>
1414
<strong>To:</strong> <%= Enum.join(email.to, ", ") %><br>
15+
<strong>Subject:</strong> <%= email.subject %><br>
16+
<strong>Content:</strong> <%= email.content %><br>
1517
<strong>Received at:</strong> <%= Timex.format!(Timex.from_unix(email.received_at, :seconds), "{ISO:Extended}") %><br>
16-
<pre><%= email.data %></pre>
1718
</li>
1819
<% end %>
1920
</ul>

mix.exs

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ defmodule TempMail.MixProject do
3030
{:iconv, "~> 1.0.10"},
3131
{:timex, "~> 3.0"},
3232
{:ecto_sql, "~> 3.0"},
33-
{:ecto_sqlite3, "~> 0.7"}
33+
{:ecto_sqlite3, "~> 0.7"},
34+
{:tzdata, "~> 1.1.2", override: true}
3435
]
3536
end
3637
end

mix.lock

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
3636
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
3737
"timex": {:hex, :timex, "3.7.11", "bb95cb4eb1d06e27346325de506bcc6c30f9c6dea40d1ebe390b262fad1862d1", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.20", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "8b9024f7efbabaf9bd7aa04f65cf8dcd7c9818ca5737677c7b76acbc6a94d1aa"},
38-
"tzdata": {:hex, :tzdata, "1.1.1", "20c8043476dfda8504952d00adac41c6eda23912278add38edc140ae0c5bcc46", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a69cec8352eafcd2e198dea28a34113b60fdc6cb57eb5ad65c10292a6ba89787"},
38+
"tzdata": {:hex, :tzdata, "1.1.2", "45e5f1fcf8729525ec27c65e163be5b3d247ab1702581a94674e008413eef50b", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "cec7b286e608371602318c414f344941d5eb0375e14cfdab605cca2fe66cba8b"},
3939
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
4040
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
4141
"websock_adapter": {:hex, :websock_adapter, "0.5.6", "0437fe56e093fd4ac422de33bf8fc89f7bc1416a3f2d732d8b2c8fd54792fe60", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "e04378d26b0af627817ae84c92083b7e97aca3121196679b73c73b99d0d133ea"},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
defmodule TempMail.Repo.Migrations.AddSubjectAndContentToEmails do
2+
use Ecto.Migration
3+
4+
def change do
5+
alter table(:emails) do
6+
add :subject, :string
7+
add :content, :text
8+
end
9+
end
10+
end

0 commit comments

Comments
 (0)