├── .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 | --------------------------------------------------------------------------------