Questo caso è esattamente ciò per cui i loop sono utili (e progettati).
Dal momento che fai cose che non rientrano nell'ambito del database, è perfettamente legittimo utilizzare i loop per loro.
I database sono progettati per archiviare dati ed eseguire query su questi dati che li restituiscono nel modo più pratico.
I database relazionali possono restituire dati sotto forma di set di righe.
I cursori (e i loop che li utilizzano) sono progettati per mantenere un set di righe stabile in modo da poter fare alcune cose con ciascuna delle sue righe.
Con "cose" qui non intendo semplici trucchi del database, ma cose reali che influenzano il mondo esterno, le cose per cui il database è progettato, che si tratti di visualizzare una tabella su una pagina Web, generare un rapporto finanziario o inviare un'e-mail.
È sbagliato usare i cursori per semplici attività di database (come trasformare un set di righe in un altro), ma è perfettamente utile usarli per cose come quella che hai descritto.
I metodi basati su set sono progettati per funzionare all'interno di una singola transazione.
Se la query set-base non riesce per qualche motivo, il database tornerà allo stato in cui era prima, ma non è possibile eseguire il "rollback" di un'e-mail inviata. Non potrai tenere traccia dei tuoi messaggi in caso di errore.