├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ ├── config.yml
│ └── feature_suggestion.yml
├── LICENSE
├── README.md
└── Workflow
├── icon.png
├── images
└── about
│ └── tmpmail.png
├── info.plist
└── notificator
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | name: Bug Report
2 | description: File a bug report
3 | body:
4 | - type: input
5 | attributes:
6 | label: Workflow version
7 | description: Open the Workflow in Alfred Preferences and find it at the top, near the description
8 | validations:
9 | required: true
10 | - type: input
11 | attributes:
12 | label: Alfred version
13 | description: In the top left corner of Alfred Preferences → General
14 | validations:
15 | required: true
16 | - type: input
17 | attributes:
18 | label: macOS version
19 | description: Click on the menubar → About This Mac
20 | validations:
21 | required: true
22 | - type: textarea
23 | attributes:
24 | label: Debugger output
25 | description: Perform the failing action with [the debugger](https://www.alfredapp.com/help/workflows/advanced/debugger/) open
26 | render: alfred_debugger
27 | validations:
28 | required: true
29 | - type: textarea
30 | attributes:
31 | label: More details
32 | description: Explain what you did, what happened, and what you expected to happen
33 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_suggestion.yml:
--------------------------------------------------------------------------------
1 | name: Feature Suggestion
2 | description: Suggest a new feature
3 | body:
4 | - type: textarea
5 | attributes:
6 | label: Feature details
7 | description: Explain the feature idea
8 | validations:
9 | required: true
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2022, Vítor Galvão
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #
Temporary Email Alfred Workflow
2 |
3 | Generate disposable email inboxes
4 |
5 | [⤓ Install on the Alfred Gallery](https://alfred.app/workflows/vitor/temporary-email)
6 |
7 | ## Usage
8 |
9 | Create a temporary email address via the `tmpmail` keyword. A random inbox name is used unless you type one.
10 |
11 | 
12 |
13 | On supported web browsers, the email inbox will open in a background tab and the address pasted to the current input field.
14 |
--------------------------------------------------------------------------------
/Workflow/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitorgalvao/temporary-email-workflow/2806ddd231df2e2908724d100f586cb14c3ca20c/Workflow/icon.png
--------------------------------------------------------------------------------
/Workflow/images/about/tmpmail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vitorgalvao/temporary-email-workflow/2806ddd231df2e2908724d100f586cb14c3ca20c/Workflow/images/about/tmpmail.png
--------------------------------------------------------------------------------
/Workflow/info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | bundleid
6 | com.vitorgalvao.alfred.temporaryemail
7 | connections
8 |
9 | 1BFF14FC-DF72-4BC9-807B-3D38432CF08D
10 |
11 |
12 | destinationuid
13 | 736622BA-E278-42DF-8121-265EDBBADFBA
14 | modifiers
15 | 0
16 | modifiersubtext
17 |
18 | vitoclose
19 |
20 |
21 |
22 | 9066A3FA-E9D2-44AF-BB72-A54ABBEB3A3D
23 |
24 |
25 | destinationuid
26 | A62BDC1B-6EF0-4884-8225-DED4378FC038
27 | modifiers
28 | 0
29 | modifiersubtext
30 |
31 | vitoclose
32 |
33 |
34 |
35 | A62BDC1B-6EF0-4884-8225-DED4378FC038
36 |
37 |
38 | destinationuid
39 | E9B13513-9247-4498-8320-6E24CF7DBDB5
40 | modifiers
41 | 0
42 | modifiersubtext
43 |
44 | sourceoutputuid
45 | 8174851A-74D2-4634-B71B-9BCC7064C9F5
46 | vitoclose
47 |
48 |
49 |
50 | destinationuid
51 | 1BFF14FC-DF72-4BC9-807B-3D38432CF08D
52 | modifiers
53 | 0
54 | modifiersubtext
55 |
56 | vitoclose
57 |
58 |
59 |
60 | E9B13513-9247-4498-8320-6E24CF7DBDB5
61 |
62 |
63 | destinationuid
64 | 1BFF14FC-DF72-4BC9-807B-3D38432CF08D
65 | modifiers
66 | 0
67 | modifiersubtext
68 |
69 | vitoclose
70 |
71 |
72 |
73 |
74 | createdby
75 | Vítor Galvão
76 | description
77 | Generate disposable email inboxes
78 | disabled
79 |
80 | name
81 | Temporary Email
82 | objects
83 |
84 |
85 | config
86 |
87 | concurrently
88 |
89 | escaping
90 | 102
91 | script
92 | function notification {
93 | ./notificator --message "${1}" --title "${alfred_workflow_name}"
94 | }
95 |
96 | readonly email_name="${1//[^[:alnum:]]}"
97 | readonly email="${email_name}@${email_service}"
98 |
99 | if [[ "${email_service}" == 'maildrop.cc' ]]; then
100 | readonly url="https://${email_service}/inbox/?mailbox=${email_name}"
101 | else
102 | readonly url="https://${email_service}/inbox/${email_name}"
103 | fi
104 |
105 | echo -n "${email}"
106 | notification 'Temporary email address copied to clipboard'
107 |
108 | # Use AppleScript instead of JXA because the latter cannot create tabs at specific indexes
109 | # Call it via the shell because otherwise the code is complicated by "using terms from"
110 | # which requires a specific browser to be installed
111 | readonly front_browser="$(osascript -e 'tell application "System Events" to return name of first process whose frontmost is true')"
112 |
113 | if [[ "${front_browser}" == 'Safari'* || "${front_browser}" == 'Webkit'* ]]; then
114 | osascript -e "
115 | tell application \"${front_browser}\" to tell front window
116 | set tabIndex to index of current tab
make new tab at after tab tabIndex with properties {URL:\"${url}\"}
117 | end tell
118 | " > /dev/null # Ignore stdout, otherwise tab info is printed
119 | elif [[ "${front_browser}" == 'Google Chrome'* || "${front_browser}" == 'Chromium'* || "${front_browser}" == 'Opera'* || "${front_browser}" == 'Vivaldi'* || "${front_browser}" == 'Brave Browser'* || "${front_browser}" == 'Microsoft Edge'* ]]; then
120 | osascript -e "
121 | tell application \"${front_browser}\" to tell front window
122 | set tabIndex to active tab index
123 | make new tab at after tab tabIndex with properties {URL:\"${url}\"}
124 | set active tab index to tabIndex
125 | end tell
126 | "
127 | # As of Orion 0.99 (127.2) and Arc 1.40.1 (49250), neither exposes tab indexes via AppleScript
128 | elif [[ "${front_browser}" == 'Orion' || "${front_browser}" == 'Arc' ]]; then
129 | osascript -e "
130 | tell application \"${front_browser}\" to tell front window
131 | make new tab with properties {URL:\"${url}\"}
132 | end tell
133 | " > /dev/null # Ignore stdout, otherwise tab info is printed
134 | # Browser without AppleScript support, such as Firefox
135 | else
136 | open "${url}"
137 | fi
138 | scriptargtype
139 | 1
140 | scriptfile
141 |
142 | type
143 | 11
144 |
145 | type
146 | alfred.workflow.action.script
147 | uid
148 | 1BFF14FC-DF72-4BC9-807B-3D38432CF08D
149 | version
150 | 2
151 |
152 |
153 | config
154 |
155 | autopaste
156 |
157 | clipboardtext
158 | {query}
159 | ignoredynamicplaceholders
160 |
161 | transient
162 |
163 |
164 | type
165 | alfred.workflow.output.clipboard
166 | uid
167 | 736622BA-E278-42DF-8121-265EDBBADFBA
168 | version
169 | 3
170 |
171 |
172 | config
173 |
174 | argumenttype
175 | 1
176 | keyword
177 | {var:email_keyword}
178 | skipuniversalaction
179 |
180 | subtext
181 | Instant disposable email
182 | text
183 | Temporary Email
184 | withspace
185 |
186 |
187 | type
188 | alfred.workflow.input.keyword
189 | uid
190 | 9066A3FA-E9D2-44AF-BB72-A54ABBEB3A3D
191 | version
192 | 1
193 |
194 |
195 | config
196 |
197 | type
198 | 0
199 |
200 | type
201 | alfred.workflow.utility.random
202 | uid
203 | E9B13513-9247-4498-8320-6E24CF7DBDB5
204 | version
205 | 1
206 |
207 |
208 | config
209 |
210 | conditions
211 |
212 |
213 | inputstring
214 |
215 | matchcasesensitive
216 |
217 | matchmode
218 | 0
219 | matchstring
220 |
221 | outputlabel
222 | Random
223 | uid
224 | 8174851A-74D2-4634-B71B-9BCC7064C9F5
225 |
226 |
227 | elselabel
228 | Specific
229 | hideelse
230 |
231 |
232 | type
233 | alfred.workflow.utility.conditional
234 | uid
235 | A62BDC1B-6EF0-4884-8225-DED4378FC038
236 | version
237 | 1
238 |
239 |
240 | readme
241 | ## Usage
242 |
243 | Create a temporary email address via the `tmpmail` keyword. A random inbox name is used unless you type one.
244 |
245 | 
246 |
247 | On supported web browsers, the email inbox will open in a background tab and the address pasted to the current input field.
248 | uidata
249 |
250 | 1BFF14FC-DF72-4BC9-807B-3D38432CF08D
251 |
252 | xpos
253 | 390
254 | ypos
255 | 25
256 |
257 | 736622BA-E278-42DF-8121-265EDBBADFBA
258 |
259 | xpos
260 | 565
261 | ypos
262 | 25
263 |
264 | 9066A3FA-E9D2-44AF-BB72-A54ABBEB3A3D
265 |
266 | xpos
267 | 30
268 | ypos
269 | 25
270 |
271 | A62BDC1B-6EF0-4884-8225-DED4378FC038
272 |
273 | xpos
274 | 185
275 | ypos
276 | 45
277 |
278 | E9B13513-9247-4498-8320-6E24CF7DBDB5
279 |
280 | xpos
281 | 295
282 | ypos
283 | 25
284 |
285 |
286 | userconfigurationconfig
287 |
288 |
289 | config
290 |
291 | default
292 | tmpmail
293 | placeholder
294 |
295 | required
296 |
297 | trim
298 |
299 |
300 | description
301 |
302 | label
303 | Email Keyword
304 | type
305 | textfield
306 | variable
307 | email_keyword
308 |
309 |
310 | config
311 |
312 | default
313 | sharklasers.com
314 | pairs
315 |
316 |
317 | Maildrop
318 | maildrop.cc
319 |
320 |
321 | Harakirimail
322 | harakirimail.com
323 |
324 |
325 | Shark Lasers
326 | sharklasers.com
327 |
328 |
329 |
330 | description
331 |
332 | label
333 | Email Service
334 | type
335 | popupbutton
336 | variable
337 | email_service
338 |
339 |
340 | version
341 | 2024.2
342 | webaddress
343 | https://github.com/vitorgalvao/temporary-email-workflow/
344 |
345 |
346 |
--------------------------------------------------------------------------------
/Workflow/notificator:
--------------------------------------------------------------------------------
1 | #!/bin/zsh
2 |
3 | ####################################################
4 | ### Created by Vítor Galvão ###
5 | ### Find the latest version at: ###
6 | ### https://github.com/vitorgalvao/notificator ###
7 | ####################################################
8 |
9 | readonly program="$(basename "${0}")"
10 |
11 | # Helpers
12 | function show_notification {
13 | /usr/bin/open "${app}" --args "${notificator_message}" "${notificator_title}" "${notificator_subtitle}" "${notificator_sound}"
14 | }
15 |
16 | function make_icns {
17 | # Setup
18 | local -r file="${1}"
19 | local -r tmp_dir="$(/usr/bin/mktemp -d)"
20 | local -r icon="${tmp_dir}/icon.icns"
21 | local -r iconset="${tmp_dir}/icon.iconset"
22 | /bin/mkdir "${iconset}"
23 |
24 | # Create iconset
25 | for size in {16,32,64,128,256,512}
26 | do
27 | /usr/bin/sips --resampleHeightWidth "${size}" "${size}" "${file}" --out "${iconset}/icon_${size}x${size}.png" &> /dev/null
28 | /usr/bin/sips --resampleHeightWidth "$((size * 2))" "$((size * 2))" "${file}" --out "${iconset}/icon_${size}x${size}@2x.png" &> /dev/null
29 | done
30 |
31 | # Convert to icns
32 | /usr/bin/iconutil --convert icns "${iconset}" --output "${icon}"
33 |
34 | # Clean up and return path to icns
35 | /bin/rm -rf "${iconset}"
36 | echo "${icon}"
37 | }
38 |
39 | function usage {
40 | echo "
41 | Trigger macOS notifications from Alfred, using the Workflow icon
42 |
43 | Usage:
44 | ${program} --message [options]
45 |
46 | Options:
47 | -m, --message Message text
48 | -t, --title Title text
49 | -s, --subtitle Subtitle text
50 | -p, --sound Sound name (from /System/Library/Sounds)
51 | -h, --help Show this help
52 | " | sed -E 's/^ {4}//'
53 | }
54 |
55 | # Options
56 | args=()
57 | while [[ "${1}" ]]
58 | do
59 | case "${1}" in
60 | -h | --help)
61 | usage
62 | exit 0
63 | ;;
64 | -m | --message)
65 | readonly notificator_message="${2}"
66 | shift
67 | ;;
68 | -t | --title)
69 | readonly notificator_title="${2}"
70 | shift
71 | ;;
72 | -s | --subtitle)
73 | readonly notificator_subtitle="${2}"
74 | shift
75 | ;;
76 | -p | --sound)
77 | readonly notificator_sound="${2}"
78 | shift
79 | ;;
80 | --)
81 | shift
82 | args+=("${@}")
83 | break
84 | ;;
85 | -*)
86 | echo "Unrecognised option: ${1}"
87 | exit 1
88 | ;;
89 | *)
90 | args+=("${1}")
91 | ;;
92 | esac
93 | shift
94 | done
95 | set -- "${args[@]}"
96 |
97 | # Check for required arguments
98 | if [[ -z "${notificator_message}" ]]
99 | then
100 | echo 'A message is mandatory! Aborting…' >&2
101 | exit 1
102 | fi
103 |
104 | readonly bundle_id="$(/usr/bin/tr -cd '[:alnum:]._-' <<< "${alfred_workflow_bundleid}")"
105 | readonly name="$(/usr/bin/tr -cd '[:alnum:]._- ' <<< "${alfred_workflow_name}")"
106 | readonly icon="${alfred_preferences}/workflows/${alfred_workflow_uid}/icon.png"
107 | readonly app="${alfred_workflow_cache}/Notificator for ${name}.app"
108 | readonly plist="${app}/Contents/Info.plist"
109 |
110 | # Exit early if Notificator exists and was modified fewer than 30 days ago
111 | if [[ -d "${app}" && "$(/bin/date -r "${app}" +%s)" -gt "$(/bin/date -v -30d +%s)" ]]
112 | then
113 | show_notification
114 | exit 0
115 | fi
116 |
117 | # Pre-build checks
118 | if [[ -z "${bundle_id}" ]]
119 | then
120 | echo "Workflow is missing the bundle identifier! Aborting…" >&2
121 | exit 1
122 | fi
123 |
124 | if [[ -z "${name}" ]]
125 | then
126 | echo "Workflow is missing the name! Aborting…" >&2
127 | exit 1
128 | fi
129 |
130 | if [[ ! -f "${icon}" ]]
131 | then
132 | echo "Workflow is missing the icon! Aborting…" >&2
133 | exit 1
134 | fi
135 |
136 | # Build Notificator
137 | readonly jxa_script='
138 | const argv = $.NSProcessInfo.processInfo.arguments.js.map(arg => arg.js)
139 | const app = Application.currentApplication()
140 | app.includeStandardAdditions = true
141 |
142 | if (argv.length < 2) { // We use "2" because the script will always see at least one argument: the applet itself
143 | argv[1] = "Opening usage instructions…"
144 | argv[2] = "Notificator is a command-line app"
145 | argv[4] = "Funk"
146 |
147 | app.openLocation("https://github.com/vitorgalvao/notificator#usage")
148 | }
149 |
150 | const message = argv[1]
151 | const title = argv[2]
152 | const subtitle = argv[3]
153 | const sound = argv[4]
154 |
155 | const options = {}
156 | if (title) options.withTitle = title
157 | if (subtitle) options.subtitle = subtitle
158 | if (sound) options.soundName = sound
159 |
160 | app.displayNotification(message, options)
161 | '
162 |
163 | [[ -d "${app}" ]] && /bin/rm -r "${app}"
164 | /bin/mkdir -p "${alfred_workflow_cache}"
165 | /usr/bin/osacompile -l JavaScript -o "${app}" -e "${jxa_script}" 2> /dev/null
166 |
167 | # Modify Notificator
168 | /usr/libexec/PlistBuddy -c "add :CFBundleIdentifier string ${bundle_id}.notificator" "${plist}"
169 | /usr/libexec/PlistBuddy -c 'add :LSUIElement string 1' "${plist}"
170 | /bin/mv "$(make_icns "${icon}")" "${app}/Contents/Resources/applet.icns"
171 |
172 | # Redo signature
173 | /usr/bin/codesign --remove-signature "${app}"
174 | /usr/bin/codesign --sign - "${app}"
175 |
176 | show_notification
177 |
--------------------------------------------------------------------------------