├── .editorconfig
├── .github
├── FUNDING.yml
└── workflows
│ └── main.yml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── images
├── demo.gif
└── logo.png
├── tmpmail
└── tmpmail.1
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_size = 4
7 | indent_style = space
8 | end_of_line = lf
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 | max_line_length = 130
12 |
13 | # https://github.com/mvdan/sh#shfmt
14 | switch_case_indent = true
15 |
16 | [*.md]
17 | trim_trailing_whitespace = false
18 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 | custom: https://www.buymeacoffee.com/sdushantha
3 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | # This is a basic workflow to help you get started with Actions
2 |
3 | name: Shellcheck
4 |
5 | # Triggers the workflow on push or pull request on all branches
6 | on: [push, pull_request]
7 |
8 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
9 | jobs:
10 | # This workflow contains a single job called "build"
11 | build:
12 | # The type of runner that the job will run on
13 | runs-on: ubuntu-latest
14 |
15 | # Steps represent a sequence of tasks that will be executed as part of the job
16 | steps:
17 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
18 | - uses: actions/checkout@v2
19 |
20 | # Runs a set of commands using the runners shell
21 | - name: Run shellcheck
22 | run: |
23 | shellcheck -s sh tmpmail
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine:3.15.4
2 |
3 | RUN apk --no-cache add curl jq w3m xclip util-linux
4 |
5 | RUN curl -L "https://raw.githubusercontent.com/sdushantha/tmpmail/master/tmpmail" > tmpmail && chmod +x tmpmail
6 |
7 | RUN mv tmpmail /bin/
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Siddharth Dushantha
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | A temporary email right from your terminal written in POSIX sh
5 |
6 |
`tmpmail` is a command line utility written in POSIX `sh` that allows you to create a temporary email address
7 | and receive emails to the temporary email address. It uses 1secmail's [API](https://www.1secmail.com/api/)
8 | to receive emails.
9 |
10 | By default `w3m` is used to render the HTML emails on the terminal.
11 | But if you prefer another text based web browser or would rather view the email in a GUI web browser such as Firefox, simply
12 | use the `--browser` argument followed by the command needed to launch the web browser of your choice.
13 |
14 |
15 |
16 |
17 |
18 | ## Dependencies
19 | - `w3m`
20 | - `curl`
21 | - [`jq`](https://github.com/stedolan/jq)
22 | - `xclip`
23 |
24 | ## Installation
25 | ### Install locally
26 |
27 | ```bash
28 | # Download the tmpmail file and make it executable
29 | $ curl -L "https://raw.githubusercontent.com/sdushantha/tmpmail/master/tmpmail" > tmpmail && chmod +x tmpmail
30 |
31 | # Then move it somewhere in your $PATH. Here is an example:
32 | $ mv tmpmail ~/bin/
33 | ```
34 |
35 | ### AUR
36 | `tmpmail` is available on the [AUR](https://aur.archlinux.org/packages/tmpmail-git/), which is currently being maintained by [Benjamin Bädorf](https://github.com/b12f)
37 |
38 | ```bash
39 | $ yay -S tmpmail-git
40 | ```
41 |
42 | ### [Pacstall](https://github.com/pacstall/pacstall) (Debian/Ubuntu)
43 | `tmpmail` is available on the [pacstall-programs repository](https://github.com/pacstall/pacstall-programs/blob/master/packages/tmpmail-bin/tmpmail-bin.pacscript), which is being currently being maintained by [wizard-28](https://github.com/wizard-28)
44 |
45 | ```
46 | $ pacstall -I tmpmail-bin
47 | ```
48 |
49 | ### Nixpkgs
50 | `tmpmail` is also available in the [nix package collection (only unstable currently)](https://search.nixos.org/packages?channel=unstable&show=tmpmail&from=0&size=50&sort=relevance&query=tmpmail), which is maintained by [legendofmiracles](https://github.com/legendofmiracles)
51 |
52 | Either add it to your system packages, install it with nix-env or try it out in a ephemeral nix-shell `nix-shell -p tmpmail`
53 |
54 | ### Docker
55 |
56 | requirements:
57 | - [docker](https://www.docker.com/)
58 | - clone this repo
59 |
60 | ```bash
61 | $ docker build -t mail .; # Dockerfile available in source code
62 | $ docker run -it mail;
63 | ```
64 |
65 | ## Usage
66 | ```console
67 | $ tmpmail --help
68 | tmpmail
69 | tmpmail -h | --version
70 | tmpmail -g [ADDRESS]
71 | tmpmail [-t | -b BROWSER] -r | ID
72 |
73 | When called with no option and no argument, tmpmail lists the messages in
74 | the inbox and their numeric IDs. When called with one argument, tmpmail
75 | shows the email message with specified ID.
76 |
77 | -b, --browser BROWSER
78 | Specify BROWSER that is used to render the HTML of
79 | the email (default: w3m)
80 | --clipboard-cmd COMMAND
81 | Specify the COMMAND to use for copying the email address to your
82 | clipboard (default: xclip -selection c)
83 | -c, --copy
84 | Copy the email address to your clipboard
85 | -d, --domains
86 | Show list of available domains
87 | -g, --generate [ADDRESS]
88 | Generate a new email address, either the specified ADDRESS, or
89 | randomly create one
90 | -h, --help
91 | Show help
92 | -r, --recent
93 | View the most recent email message
94 | -t, --text
95 | View the email as raw text, where all the HTML tags are removed.
96 | Without this option, HTML is used.
97 | --version
98 | Show version
99 | ```
100 |
101 | ### Examples
102 | Create random email
103 | ```console
104 | $ tmpmail --generate
105 | xoithrjagpx@1secmail.net
106 | ```
107 |
108 | Create custom email
109 | ```console
110 | $ tmpmail --generate mycustomemail@1secmail.com
111 | mycustomemail@1secmail.com
112 | ```
113 |
114 | View the inbox
115 | ```console
116 | $ tmpmail
117 | [ Inbox for wdebivbyjor@1secmail.com ]
118 |
119 | 83414443 username@example.com Test Email
120 | ```
121 |
122 | View the email
123 | ```console
124 | $ tmpmail 83414443
125 | ```
126 |
127 | View the most recent email
128 | ```console
129 | $ tmpmail -r
130 | ```
131 |
132 | View emails as pure text
133 | ```console
134 | $ tmpmail -t 83414443
135 | To: wdebivbyjor@1secmail.com
136 | From: username@example.com
137 | Subject: Test Email
138 |
139 | Hello World
140 |
141 | [Attachments]
142 | https://is.gd/aBCdEf [apple.jpg]
143 | https://is.gd/AbCDeF [ball.jpg]
144 | ```
145 |
146 | ## Credits
147 | This script is heavily inspired by Mitch Weaver's [`1secmail`](https://github.com/mitchweaver/bin/blob/master/OLD/1secmail) script
148 |
--------------------------------------------------------------------------------
/images/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdushantha/tmpmail/637090f0f056df4550b52547f9cf4699f4bfd755/images/demo.gif
--------------------------------------------------------------------------------
/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sdushantha/tmpmail/637090f0f056df4550b52547f9cf4699f4bfd755/images/logo.png
--------------------------------------------------------------------------------
/tmpmail:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | #
3 | # by Siddharth Dushantha 2020
4 | #
5 | # Dependencies: jq, curl, w3m
6 | #
7 |
8 | version=1.2.3
9 |
10 | # By default 'tmpmail' uses 'w3m' as it's web browser to render
11 | # the HTML of the email
12 | browser="w3m"
13 |
14 | # The default command that will be used to copy the email address to
15 | # the user's clipboard when running 'tmpmail --copy'
16 | copy_to_clipboard_cmd="xclip -selection c"
17 |
18 | # If the value is set to 'true' tmpmail will convert the HTML email
19 | # to raw text and send that to stdout
20 | raw_text=false
21 |
22 | # Everything related to 'tmpmail' will be stored in /tmp/tmpmail
23 | # so that the old emails and email addresses get cleared after
24 | # restarting the computer
25 | tmpmail_dir="/tmp/tmpmail"
26 |
27 | # tmpmail_email_address is where we store the temporary email address
28 | # that gets generated. This prevents the user from providing
29 | # the email address everytime they run tmpmail
30 | tmpmail_email_address="$tmpmail_dir/email_address"
31 |
32 | # tmpmail.html is where the email gets stored.
33 | # Even though the file ends with a .html extension, the raw text version of
34 | # the email will also be stored in this file so that w3m and other browsers
35 | # are able to open this file
36 | tmpmail_html_email="$tmpmail_dir/tmpmail.html"
37 |
38 | # Default 1secmail API URL
39 | tmpmail_api_url="https://www.1secmail.com/api/v1/"
40 |
41 | usage() {
42 | # Using 'cat << EOF' we can easily output a multiline text. This is much
43 | # better than using 'echo' for each line or using '\n' to create a new line.
44 | cat <"$tmpmail_email_address"
164 |
165 | # If this function was called because the user wanted to generate a new
166 | # email address, show them the email address
167 | [ "$externally" = true ] && cat "$tmpmail_email_address" && printf "\n"
168 | }
169 |
170 | get_email_address() {
171 | # This function is only called once and that is when this script
172 | # get executed. The output of this function gets stored in $email_address
173 | #
174 | # If the file that contains the email address is empty,
175 | # that means we do not have an email address, so generate one.
176 | [ ! -s "$tmpmail_email_address" ] && generate_email_address
177 |
178 | # Output the email address by getting the first line of $tmpmail_email
179 | head -n 1 "$tmpmail_email_address"
180 | }
181 |
182 | list_emails() {
183 | # List all the received emails in a nicely formatted order
184 | #
185 | # Fetch the email data using 1secmail's API
186 | data=$(curl -sL "$tmpmail_api_url?action=getMessages&login=$username&domain=$domain")
187 |
188 | # Using 'jq' we get the length of the JSON data. From this we can determine whether or not
189 | # the email address has gotten any emails
190 | data_length=$(printf %s "$data" | jq length)
191 |
192 | # We are showing what email address is currently being used
193 | # in case the user has forgotten what the email address was.
194 | printf "[ Inbox for %s ]\n\n" "$email_address"
195 |
196 | # If the length of the data we got is 0, that means the email address
197 | # has not received any emails yet.
198 | [ "$data_length" -eq 0 ] && echo "No new mail" && exit
199 |
200 | # This is where we store all of our emails, which is then
201 | # displayed using 'column'
202 | inbox=""
203 |
204 | # Go through each mail that has been received
205 | index=1
206 | while [ $index -le "${data_length}" ]; do
207 | # Since arrays in JSON data start at 0, we must subtract
208 | # the value of $index by 1 so that we dont miss one of the
209 | # emails in the array
210 | mail_data=$(printf %s "$data" | jq -r ".[$index-1]")
211 | id=$(printf %s "$mail_data" | jq -r ".id")
212 | from=$(printf %s "$mail_data" | jq -r ".from")
213 | subject=$(printf %s "$mail_data" | jq -r ".subject")
214 |
215 | # The '||' are used as a divideder for 'column'. 'column' will use this divider as
216 | # a point of reference to create the division. By default 'column' uses a blank space
217 | # but that would not work in our case as the email subject could have multiple white spaces
218 | # and 'column' would split the words that are seperated by white space, in different columns.
219 | inbox="$inbox$id ||$from ||$subject\n"
220 | index=$((index + 1))
221 | done
222 |
223 | # Show the emails cleanly
224 | printf "%b" "$inbox" | column -t -s "||"
225 | }
226 |
227 | randomize() {
228 | # We could use 'shuf' and 'sort -R' but they are not a part of POSIX
229 | awk 'BEGIN {srand();} {print rand(), $0}' | \
230 | sort -n -k1 | cut -d' ' -f2
231 | }
232 |
233 | view_email() {
234 | # View an email by providing it's ID
235 | #
236 | # The first argument provided to this function will be the ID of the email
237 | # that has been received
238 | email_id="$1"
239 | data=$(curl -sL "$tmpmail_api_url?action=readMessage&login=$username&domain=$domain&id=$email_id")
240 |
241 | # After the data is retrieved using the API, we have to check if we got any emails.
242 | # Luckily 1secmail's API is not complicated and returns 'Message not found' as plain text
243 | # if our email address as not received any emails.
244 | # If we received the error message from the API just quit because there is nothing to do
245 | [ "$data" = "Message not found" ] && die "Message not found"
246 |
247 | # We pass the $data to 'jq' which extracts the values
248 | from=$(printf %s "$data" | jq -r ".from")
249 | subject=$(printf %s "$data" | jq -r ".subject")
250 | html_body=$(printf %s "$data" | jq -r ".htmlBody")
251 | attachments=$(printf %s "$data" | jq -r ".attachments | length")
252 |
253 | # If you get an email that is in pure text, the .htmlBody field will be empty and
254 | # we will need to get the content from .textBody instead
255 | [ -z "$html_body" ] && html_body="$(printf %s "$data" | jq -r ".textBody")
"
256 |
257 | # Create the HTML with all the information that is relevant and then
258 | # assigning that HTML to the variable html_mail. This is the best method
259 | # to create a multiline variable
260 | html_mail=$(cat <To: $email_address
262 | From: $from
263 | Subject: $subject
264 | $html_body
265 |
266 | EOF
267 | )
268 |
269 | if [ ! "$attachments" = "0" ]; then
270 | html_mail="$html_mail
[Attachments]
"
271 |
272 | index=1
273 | while [ "$index" -le "$attachments" ]; do
274 | filename=$(printf %s "$data" | jq -r ".attachments | .[$index-1] | .filename")
275 | link="$tmpmail_api_url?action=download&login=$username&domain=$domain&id=$email_id&file=$filename"
276 | html_link="$filename
"
277 |
278 | if [ "$raw_text" = true ]; then
279 | # The actual url is way too long and does not look so nice in STDOUT.
280 | # Therefore we will shortening it using is.gd so that it looks nicer.
281 | link=$(curl -s -F"url=$link" "https://is.gd/create.php?format=simple")
282 | html_mail="$html_mail$link [$filename]
"
283 | else
284 | html_mail="$html_mail$html_link"
285 | fi
286 |
287 | index=$((index + 1))
288 | done
289 | fi
290 |
291 | # Save the $html_mail into $tmpmail_html_email
292 | printf %s "$html_mail" >"$tmpmail_html_email"
293 |
294 | # If the '--text' flag is used, then use 'w3m' to convert the HTML of
295 | # the email to pure text by removing all the HTML tags
296 | [ "$raw_text" = true ] && w3m -dump "$tmpmail_html_email" && exit
297 |
298 | # Open up the HTML file using $browser. By default,
299 | # this will be 'w3m'.
300 | $browser "$tmpmail_html_email"
301 | }
302 |
303 |
304 | view_recent_email() {
305 | # View the most recent email.
306 | #
307 | # This is done by listing all the received email like you
308 | # normally see on the terminal when running 'tmpmail'.
309 | # We then grab the ID of the most recent
310 | # email, which the first line.
311 | mail_id=$(list_emails | head -3 | tail -1 | cut -d' ' -f 1)
312 | view_email "$mail_id"
313 | }
314 |
315 |
316 | copy_email_to_clipboard(){
317 | # Copy the email thats being used to the user's clipboard
318 | $copy_to_clipboard_cmd < $tmpmail_email_address
319 | }
320 |
321 |
322 | die() {
323 | # Print error message and exit
324 | #
325 | # The first argument provided to this function will be the error message.
326 | # Script will exit after printing the error message.
327 | printf "%b\n" "Error: $1" >&2
328 | exit 1
329 | }
330 |
331 | main() {
332 | # Iterate of the array of dependencies and check if the user has them installed.
333 | # We are checking if $browser is installed instead of checking for 'w3m'. By doing
334 | # this, it allows the user to not have to install 'w3m' if they are using another
335 | # browser to view the HTML.
336 | #
337 | # dep_missing allows us to keep track of how many dependencies the user is missing
338 | # and then print out the missing dependencies once the checking is done.
339 | dep_missing=""
340 |
341 | # The main command from $copy_to_clipboard_cmd
342 | # Example:
343 | # xclip -selection c
344 | # ├───┘
345 | # └ This part
346 | clipboard=${copy_to_clipboard_cmd%% *}
347 |
348 | for dependency in jq $browser $clipboard curl; do
349 | if ! command -v "$dependency" >/dev/null 2>&1; then
350 | # Append to our list of missing dependencies
351 | dep_missing="$dep_missing $dependency"
352 | fi
353 | done
354 |
355 | if [ "${#dep_missing}" -gt 0 ]; then
356 | printf %s "Could not find the following dependencies:$dep_missing"
357 | exit 1
358 | fi
359 |
360 | # Create the $tmpmail_dir directory and dont throw any errors
361 | # if it already exists
362 | mkdir -p "$tmpmail_dir"
363 |
364 | # Get the email address and save the value to the email_address variable
365 | email_address="$(get_email_address)"
366 |
367 | # ${VAR#PATTERN} Removes shortest match of pattern from start of a string.
368 | # In this case, it takes the email_address and removed everything after
369 | # the '@' symbol which gives us the username.
370 | username=${email_address%@*}
371 |
372 | # ${VAR%PATTERN} Remove shortest match of pattern from end of a string.
373 | # In this case, it takes the email_address and removes everything until the
374 | # period '.' which gives us the domain
375 | domain=${email_address#*@}
376 |
377 | # If no arguments are provided just the emails
378 | [ $# -eq 0 ] && list_emails && exit
379 |
380 | while [ "$1" ]; do
381 | case "$1" in
382 | --help | -h) usage && exit ;;
383 | --domains | -d) show_list_of_domains && exit ;;
384 | --generate | -g) generate_email_address true "$2" && exit ;;
385 | --clipboard-cmd) copy_to_clipboard_cmd="$2" ;;
386 | --copy | -c) copy_email_to_clipboard && exit ;;
387 | --browser | -b) browser="$2" ;;
388 | --text | -t) raw_text=true ;;
389 | --version) echo "$version" && exit ;;
390 | --recent | -r) view_recent_email && exit ;;
391 | *[0-9]*)
392 | # If the user provides number as an argument,
393 | # assume its the ID of an email and try getting
394 | # the email that belongs to the ID
395 | view_email "$1" && exit
396 | ;;
397 | -*) die "option '$1' does not exist" ;;
398 | esac
399 | shift
400 | done
401 | }
402 |
403 | main "$@"
404 |
--------------------------------------------------------------------------------
/tmpmail.1:
--------------------------------------------------------------------------------
1 | .Dd 2020-10-01
2 | .Dt tmpmail 1
3 | .Os
4 | .Sh NAME
5 | .Nm tmpmail
6 | .Nd temporary email
7 | .Sh SYNOPSIS
8 | .Nm
9 | .Nm
10 | .Fl h | -version
11 | .Nm
12 | .Fl g Op Ar ADDRESS
13 | .Nm
14 | .Op Fl t | b Ar BROWSER
15 | .Fl r | Ar ID
16 | .Sh DESCRIPTION
17 | .Nm
18 | is a command line utility written in POSIX shell that allows you to create a temporary email address and receive emails to the temporary email address. It uses 1secmail's API to receive emails.
19 | .Ss Options and Arguments
20 | When called with no option and no argument,
21 | .Nm
22 | lists the messages in the inbox and their numeric IDs.
23 | When called with one argument,
24 | .Nm
25 | shows the email message with specified
26 | .Ar ID .
27 | .Bl -tag -width Ds
28 | .It Fl b , Fl Fl browser Ar BROWSER
29 | Specify
30 | .Ar BROWSER
31 | (default: w3m) that is used to render the HTML of the email
32 | .It Fl Fl clipboard-cmd Ar COMMAND
33 | Specify the COMMAND to use for copying the email address to your
34 | clipboard (default: xclip -selection c)
35 | .It Fl g , Fl Fl generate Op Ar ADDRESS
36 | Generate a new email address, either the specified
37 | .Ar ADDRESS ,
38 | or randomly create one
39 | .It Fl h , Fl Fl help
40 | Show help
41 | .It Fl r , Fl Fl recent
42 | View the most recent email message
43 | .It Fl t , Fl Fl text
44 | View the email as raw text, where all the HTML tags are removed. Without this option, HTML is used.
45 | .It Fl Fl version
46 | Show version
47 | .El
48 |
--------------------------------------------------------------------------------