Why plain onEdit silently fails
The first time I tried this I pasted a function named onEdit, added a MailApp.sendEmail call inside it, edited the cell, and heard nothing. No error. No email. The function ran fine — it just skipped the email without complaint.
Google Apps Script has two tiers of triggers. Simple triggers (named onEdit, onOpen, onChange) run without asking for permissions and are deliberately sandboxed: they cannot call services that act on your behalf, including MailApp and GmailApp. The quota-guarded services require OAuth consent, and simple triggers never go through that flow.
Installable triggers work differently. You register them through the Triggers UI (or programmatically via ScriptApp.newTrigger), and the first time you save one, Apps Script prompts for authorization. After that, the function runs with your credentials and MailApp works. The function name does not have to be onEdit — in fact naming it something else makes the distinction obvious.