├── .github ├── FUNDING.yml └── workflows │ └── main.yml ├── LICENSE ├── README.md ├── images ├── demo.gif └── logo.png └── tmpsms /.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 tmpsms 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 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 | # tmpsms no longer works 2 | 3 | tmpsms was pretty much a wrapper around [Upmasked's](https://upmasked.com/) temporary SMS service but Upmasked seems to have taken down their website as well as their [GitHub account](https://github.com/upmasked/). `tmpsms` may come back in the future if I can find another reliable SMS service. But even if I do find one sometime soon, it unlikely I will further develop `tmpsms` to use that service as I have other priorities. 4 | 5 | ---- 6 | 7 |

8 | 9 |

10 | 11 |

A temporary SMS right from your terminal written in POSIX sh

12 |

13 | 14 |

15 | 16 | `tmpsms` is a command line utility written in POSIX `sh` that allows you to get a 17 | temporary phone number and receive SMSes. It uses [Upmasked](https://upmasked.com/) temporary SMS service in order to receive the messages. This is a very useful 18 | tool for those testing applications during bug bounty hunting or who just need some privacy and don't want to use a personal phone number. 19 | This is easy to use with simple outputs. `tmpsms` can be integrated with other scripts to improve your workflow. 20 | 21 | ## Dependencies 22 | - `curl` 23 | - [`jq`](https://github.com/stedolan/jq) 24 | - [`fzf`](https://github.com/junegunn/fzf) 25 | 26 | ## Installation 27 | ```bash 28 | # Download the tmpsms file and make it executable 29 | $ curl -L "https://git.io/tmpsms" > tmpsms && chmod +x tmpsms 30 | 31 | # Then move it somewhere in your $PATH. Here is an example: 32 | $ mv tmpsms ~/bin/ 33 | ``` 34 | 35 | ## Usage 36 | ```console 37 | $ tmpsms --help 38 | tmpsms [--count ] 39 | tmpsms init [--fzf ] 40 | tmpsms -h | --version 41 | 42 | When called with no options or commands, tmpsms lists 43 | the 3 newest messages. 44 | 45 | Options 46 | -h, --help Show this help message 47 | -c, --count Only show the newest messages 48 | --version Show version 49 | 50 | Commands 51 | init Initialize a new phone number by selecting one 52 | from the available ones using 'fzf' 53 | --fzf Extra arguments to use for 'fzf' 54 | ``` 55 | 56 | ## Examples 57 | Initialize a new phone number 58 | ```console 59 | $ tmpsms init 60 | ``` 61 | 62 | View the 5 newest messages. By default `tmpsms` shows the 3 newest messages. 63 | ```console 64 | $ tmpsms --count 5 65 | ``` 66 | 67 | If you find it a hassle to rerun `tmpsms` every few seconds, use `watch` with a delay of 5 seconds. Upmasked only updates messages every 5 seconds. 68 | ```console 69 | $ watch -n 5 "tmpsms" 70 | ``` 71 | -------------------------------------------------------------------------------- /images/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdushantha/tmpsms/06bd6b0fc89485096ec51dede3f72806c158daac/images/demo.gif -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdushantha/tmpsms/06bd6b0fc89485096ec51dede3f72806c158daac/images/logo.png -------------------------------------------------------------------------------- /tmpsms: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # 3 | # by Siddharth Dushantha 4 | # 5 | 6 | VERSION="1.0.0" 7 | 8 | # Everything related to 'tmpsms' will be stored in this directory. Once the 9 | # computer get restarted, this directory gets deleted. 10 | TMPSMS_DIR="/tmp/tmpsms" 11 | 12 | # The phone number that the user has selected gets stored in this file so that 13 | # the do not have reselect at ever run. 14 | TMPSMS_PHONE_NUMBER="$TMPSMS_DIR/phonenumber.txt" 15 | 16 | # 'fzf' is used to allow the user to select a phone number. This variable 17 | # stores extra arguments which the user might to provide, so that 'fzf' 18 | # behaves to their liking. 19 | FZF_ARGUMENTS="" 20 | 21 | # The temporary SMS service is provided by Upmasked 22 | API="https://upmasked.com" 23 | 24 | usage(){ 25 | # Using 'cat << EOF' we can easily output a multiline text. This is much 26 | # better than using 'echo' for each line or using '\n' to create a new line. 27 | cat <] 29 | tmpsms init [--fzf ] 30 | tmpsms -h | --version 31 | 32 | When called with no options or commands, tmpsms lists 33 | the 3 newest messages. 34 | 35 | Options 36 | -h, --help Show this help message 37 | -c, --count Only show the newest messages 38 | --version Show version 39 | 40 | Commands 41 | init Initialize a new phone number by selecting one 42 | from the available ones using 'fzf' 43 | --fzf Extra arguments to use for 'fzf' 44 | EOF 45 | } 46 | 47 | print_error(){ 48 | # Print error message 49 | # 50 | # The first argument provided to this function will be the error message. 51 | # Script will exit after printing the error message. 52 | printf "%s\n" "Error: $1" >&2 53 | exit 1 54 | } 55 | 56 | 57 | select_phone_number(){ 58 | # There are 2 ways which this function is called in this script. 59 | # [1] The user wants to initilize a new phone number by running 'tmpsms init' 60 | # [2] The user runs 'tmpsms' to check for new messages, but $TMPSMS_PHONE_NUMBER 61 | # does't exist. Therefore they have to select phone number before we can 62 | # show them the messages. 63 | # 64 | # When the function 'select_phone_number()' is called with the argument 'true' 65 | # that means this function was called becaues the user ran 'tmpsms init' 66 | # 67 | # We need this variable so we can know whether or not we need to show the user 68 | # the phone number they have selected. If they ran 'tmpsms init', then we will 69 | # show them the phone number they selected. This is so that they can easily 70 | # copy and paste it to whatever site that needs the phone number. 71 | EXTERNALLY=${1:-false} 72 | 73 | # Fetch the available phone numbers 74 | DATA=$(curl -s "$API/api/sms/numbers") 75 | 76 | # Using 'jq' we are able to get the length of the JSON data retreived from 77 | # API. The length indicates the the total number of phone numbers available. 78 | DATA_LENGTH=$(printf %s "$DATA" | jq length) 79 | 80 | # This is where we store the phone numbers which then gets shown to the user 81 | # through 'fzf' so that they can select one. 82 | PHONE_NUMBERS="" 83 | 84 | index=1 85 | while [ $index -le "$DATA_LENGTH" ]; do 86 | # Since arrays in JSON data start at 0, we must subtract 87 | # the value of $index by 1 so that we dont miss one of the 88 | # phone numbers in the array 89 | PHONE_NUMBER_INFO=$(printf %s "$DATA" | jq -r ".[$index-1]") 90 | PHONE_NUMBER=$(printf %s "$PHONE_NUMBER_INFO" | jq -r ".number") 91 | COUNTRY_CODE=$(printf %s "$PHONE_NUMBER_INFO" | jq -r ".country") 92 | 93 | PHONE_NUMBERS="$PHONE_NUMBERS$COUNTRY_CODE +$PHONE_NUMBER\n" 94 | index=$((index+1)) 95 | done 96 | 97 | # By default we use 'fzf' without any arguments in order to display the 98 | # phone numbers they can use. If the '--fzf' argument is passed along with 99 | # 'fzf' arguments, 'tmpsms' will make sure to use them. 100 | FZF_COMMAND="fzf" 101 | [ -n "$FZF_ARGUMENTS" ] && FZF_COMMAND="fzf $FZF_ARGUMENTS" 102 | 103 | # If the user did not select a phone number then quit 'tmpsms' as the 104 | # user might have just wanted to check if there were any new number 105 | # that they could use. 106 | SELECTION=$(printf %b "$PHONE_NUMBERS" | $FZF_COMMAND) 107 | [ -z "$SELECTION" ] && print_error "Phone number was not selected" 108 | 109 | # Store the selected phone number in $TMPSMS_PHONE_NUMBER for later use 110 | printf %s "$SELECTION" > "$TMPSMS_PHONE_NUMBER" 111 | 112 | # If the user ran 'tmpsms init', then show them their selection 113 | [ "$EXTERNALLY" = true ] && printf "%s\n" "$SELECTION" 114 | } 115 | 116 | list_messages(){ 117 | # By default, the 3 newest messages are shown. But if the user would like 118 | # to see more of the messages, they can provide how many they want to see 119 | # by using the '--count' option. 120 | COUNT="${1:-3}" 121 | 122 | # The provided value to '--count' must be an interger. We can verify that it is 123 | # an integer by checking if $COUNT matches the regex. 124 | REGEX='^[0-9]+$' 125 | if ! printf %s "$COUNT" | grep -Eq "$REGEX";then 126 | print_error "'$COUNT' is not an integer" 127 | fi 128 | 129 | # If /tmp/tmpsms/phonenumber.txt does not exist or is empty that means that 130 | # the user has not initialized a phone number yet. 131 | [ ! -s "$TMPSMS_PHONE_NUMBER" ] && print_error "A phone number must be initilzied in order to view the messages" 132 | 133 | # The country code is needed because it gets displayed to the user. It may 134 | # be useful for the user to know which country the phone number is from 135 | # so that they dont have to guess by looking at the area code. 136 | COUNTRY_CODE=$(awk -F" " '{print $1}' < $TMPSMS_PHONE_NUMBER) 137 | PHONE_NUMBER=$(awk -F"+" '{print $2}' < $TMPSMS_PHONE_NUMBER) 138 | DATA=$(curl -s "$API/api/sms/messages/$PHONE_NUMBER") 139 | 140 | # Even though we are using the phone numbers that are available on 141 | # upmasked.com, there is a chance that they might remove one of the numbers. 142 | # The checking needs to be done in case the phone number that is stored in 143 | # $TMPSMS_PHONE_NUMBER has been removed. 144 | if printf %s "$DATA" | grep -Eq "Not Found"; then 145 | print_error "Looks like the phone number '+$PHONE_NUMBER' no longer exists. Initialize a new one and try again." 146 | fi 147 | 148 | DATA_LENGTH=$(printf %s "$DATA" | jq length) 149 | 150 | # If the number of messages the user wants to view is greater than the 151 | # number of messages that are available, then make sure to show 152 | # all the messages that are available. 153 | [ "$COUNT" -gt "$DATA_LENGTH" ] && COUNT="$DATA_LENGTH" 154 | 155 | # Show a nice little header before showing the messages 156 | printf "%s\n\n" "[ Messages for +$PHONE_NUMBER ($COUNTRY_CODE) ]" 157 | 158 | # All the messages get stored in here 159 | MESSAGES="" 160 | 161 | index=1 162 | while [ $index -le "$COUNT" ]; do 163 | # Since arrays in JSON data start at 0, we must subtract 164 | # the value of $index by 1 so that we dont miss one of the 165 | # messages in the array 166 | MESSAGE_DATA=$(printf %s "$DATA" | jq -r ".[$index-1]") 167 | BODY=$(printf %s "$MESSAGE_DATA" | jq -r ".body" | tr "\n" " ") 168 | SENDER=$(printf %s "$MESSAGE_DATA" | jq -r ".originator") 169 | 170 | # The '||' is used as a divider for 'column'. 'column' will use this 171 | # divider as a point of reference to create the division. By default 172 | # 'column' uses a blank space but that would not work in our case as the 173 | # message could have multiple white spaces and 'column' would 174 | # split the words that are seperated by white space, in different columns. 175 | MESSAGES="$MESSAGES$SENDER ||$BODY\n" 176 | 177 | index=$((index+1)) 178 | done 179 | 180 | # Show the messages cleanly 181 | printf "%b" "$MESSAGES" | column -t -s "||" 182 | } 183 | 184 | main(){ 185 | # Iterate the array of dependencies and check if the user has them installed. 186 | for dependency in jq curl fzf; do 187 | if ! command -v "$dependency" >/dev/null 2>&1; then 188 | print_error "Could not find '$dependency', is it installed?" 189 | fi 190 | done 191 | 192 | # Create the $TMPSMS_DIR directory and dont throw any errors 193 | # if it already exists 194 | mkdir -p "$TMPSMS_DIR" 195 | 196 | # If no arguments are provided just show the messages 197 | [ $# -eq 0 ] && list_messages && exit 0 198 | 199 | while [ "$1" ]; do 200 | case "$1" in 201 | init) 202 | case "$2" in 203 | --fzf) FZF_ARGUMENTS="$3" && select_phone_number true ;; 204 | "") select_phone_number true ;; 205 | esac ;; 206 | --help | -h) usage && exit ;; 207 | --count | -c) list_messages "$2" && shift 2;; 208 | --version) printf %s "$VERSION" && exit ;; 209 | -*) print_error "option '$1' does not exist" ;; 210 | *) print_error "command '$1' does not exist" ;; 211 | esac 212 | shift 213 | done 214 | } 215 | 216 | main "$@" 217 | --------------------------------------------------------------------------------