Hack 62. Warn Before Sending Gmail Messages with Missing Attachments

 < Day Day Up > 

Hack 62. Warn Before Sending Gmail Messages with Missing Attachments

Never again forget to attach a file to your email .

It's too easy to forget to attach files when sending email. You send off the message, and a few minutes later you get a puzzled reply asking, "Was there supposed to be a file with this?"

Some desktop mail applications use heuristics to check for this condition and prompt you before sending your message. However, I have never seen this incorporated in a web mail application. Using Greasemonkey, we can guess with pretty good accuracy that a message was supposed to contain an attachment if it contains words such as attachment or files . If such a message actually contains no files, then we can show a warning before sending the message.

7.4.1. The Code

This user script runs in both the Reply and Compose frames in Gmail. These can be identified by their view=cw and view=page query string parameters.

The script listens for click events on the Send buttons . When the user clicks one of them, the script gets the contents of the message text box and scans each line of the message for any occurrences of specific keywords. Since messages can contain quoted text copied from a previous message, we intentionally ignore lines that start with >.

If we find any occurrences of attachment or files , we check whether there are any attachments. If there are no attachments, we prompt the user to confirm that she really wants to send the message.

You can access forms, form elements, images, and links by their elements' name attributes as well as their id attributes. If the element you need to modify is one of these types but doesn't have a unique id attribute, check to see if it has a unique name attribute instead.


Save the following user script as missingattachments.user.js :

// ==UserScript==

	// @name		 Missing Attachment

	// @namespace	 http://youngpup.net/

	// @description  Warn before sending Gmail messages without attachments

	// @include      http*://mail.google.com/mail/?*view=cv*

	// @include      http*://mail.google.com/mail/?*view=page*

	// ==/UserScript==



	// based on code by Aaron Boodman

	// and included here with his gracious permission



	// add more keywords here if necessary

	var words = ["attach", "attachment", "attached", "file", "files"];



	// creates a regex like of the form /\b(foobarbaz)\b/i

	var regex = new RegExp("\b(" + words.join("") + ")\b", "i");



	var form = document.getElementById("compose_form");



	document.addEventListener("click", function(e) { 

		if (e.target.id != "send") { return true; } 

		var allLines = form.elements.namedItem('msgbody').value.split("\n"); 

		for (var i = 0, line; line = allLines[i]; i++) {

			// by convention, reply lines start with ">". Some people like

			// to be clever and use other characters. If you encounter this,

			// you can test for those characters as well.

			if (line[0] == ">") { continue; }

			if (!line.match(regex)) { continue; }

			if (isFileAttached()) { continue; }

			if (!window.confirm("WARNING\n\n" +

				"This message mentions attachments, but none " +

				"are included.\n\n" +

				"Really send?\n\n" +

				"Suspicious line:\n" +

				"\"" + line + "\"")) {

				e.stopPropagation();

			}

			break;

		}

	}, true);



	function isFileAttached() {

		var iter = document.evaluate(".//input[@type='file']",

			form, null, XPathResult.ANY_TYPE, null);

		var input;

		while (input = iter.iterateNext()) {

			if (input.value != "") {

				return true;

			}

		}

		return false;

	}

The word-boundary regular expression assertion \b is the best way to tell the difference between foo and foobar . The word boundary matches when a word character ( a-z, A-Z, 0-9 , -and _) is preceded or followed by a nonword character.

It's fast and easy to create regular expressions in JavaScript using the literal form (i.e., /foobar/ ). But you might need to construct an expression dynamically, from a string that you don't know beforehand. To do this, create an instance of the RegExp object, which takes a string argument. This creates an additional problem: backslashes have special meaning inside JavaScript strings. To insert a backslash in the regular expression defined as a string, you need two backslashes. So, /hello\?/ becomes "hello\\?" , and /c:\\/ becomes "c:\\\\" .

7.4.2. Running the Hack

After installing the user script (Tools Install This User Script), log into Gmail at http://mail.google.com and start a new message. Add some text to the message body, such as, "Hi Bob, the spreadsheet you requested is attached. Please review." Press the Send button without attaching any files. The script pops up a dialog to confirm that you really intended to send the message without any attachments, as shown in Figure 7-4.

Figure 7-4. Confirming sending without attachments

If you click OK, Gmail will send the message as usual. If you click Cancel, you will stay on the message composition page, and you can click "Attach a file."

Aaron Boodman

 < Day Day Up >