public static async Task RunAsync([QueueTrigger("mailservice", Connection = "AzureWebJobsStorage")] QueueMail myQueueItem, TraceWriter log, ExecutionContext context) { SmtpServer smtpServer; var toDomain = myQueueItem.To.Split('@').Last(); if (Filters.Contains(toDomain)) { var lua = $@" local function GetServer(keys) for _,key in ipairs(keys) do local count = redis.call('GET', key) if(count ~= 1) then local current = redis.call('INCR', key) if(current == 1) then redis.call('EXPIRE', key, {LockSeconds}) return key end end end return nil end return GetServer(KEYS)"; var redisKeys = Enumerable.Range(0, SmtpServers.Count).Select(p => (RedisKey)$"{p}:{toDomain}") .ToArray(); var result = Redis.Value.GetDatabase(RedisDbNumber).ScriptEvaluate(lua, redisKeys); if (result.IsNull) { throw new ConstraintException(); } var index = int.Parse(result.ToString().Split(':').First()); smtpServer = SmtpServers[index]; } else { smtpServer = SmtpServers[0]; } var smtpClient = new SmtpClient(smtpServer.Host, smtpServer.Port) { Credentials = new NetworkCredential(smtpServer.UserName, smtpServer.Password) }; var mail = new MailMessage(myQueueItem.From, string.Join(",", myQueueItem.To)) { Subject = myQueueItem.Subject, Body = myQueueItem.Body, BodyEncoding = Encoding.UTF8, IsBodyHtml = true }; if (myQueueItem.AttachedBlobNames.Any()) { if (!await BlobContainer.Value.ExistsAsync()) { throw new Exception($"No blob"); } var tasks = myQueueItem.AttachedBlobNames.AsParallel().Select(blobname => Task.Run(async() => { var block = BlobContainer.Value.GetBlockBlobReference(blobname); if (!await block.ExistsAsync()) { throw new Exception($"No block"); } var stream = await block.OpenReadAsync(); var fileName = blobname.Split('/').Last(); return(new Attachment(stream, fileName)); })).ToArray(); var attachments = await Task.WhenAll(tasks); foreach (var attachment in attachments) { mail.Attachments.Add(attachment); } } smtpClient.SendCompleted += (sender, e) => { smtpClient.Dispose(); mail.Dispose(); if (e.Cancelled) { throw new SmtpException($"Cancelled by smtp server."); } if (e.Error != null) { throw e.Error; } if (!(e.UserState is string[] blobnames)) { return; } if (blobnames.Any()) { blobnames.AsParallel().ForAll(async blobname => await BlobContainer.Value.GetBlockBlobReference(blobname).DeleteAsync()); } }; smtpClient.SendAsync(mail, myQueueItem.AttachedBlobNames); }
public static async Task <IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req, TraceWriter log) { if (!req.Form.TryGetValue("From", out var from)) { return(new BadRequestErrorMessageResult($"Key:From is missing.")); } if (!req.Form.TryGetValue("To", out var to)) { return(new BadRequestErrorMessageResult($"Key:To is missing.")); } if (!req.Form.TryGetValue("Subject", out var subject)) { return(new BadRequestErrorMessageResult($"Key:Subject is missing.")); } if (!req.Form.TryGetValue("Body", out var body)) { return(new BadRequestErrorMessageResult($"Key:Body is missing.")); } var blobNames = new ConcurrentBag <string>(); if (req.Form.Files.Count > 0) { if (await BlobContainer.Value.CreateIfNotExistsAsync()) { await BlobContainer.Value.SetPermissionsAsync(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Container }); } foreach (var file in req.Form.Files) { var fileName = file.FileName; string blobName; CloudBlockBlob block; do { blobName = $"{Guid.NewGuid()}/{fileName}"; block = BlobContainer.Value.GetBlockBlobReference(blobName); } while (await block.ExistsAsync()); blobNames.Add(blobName); var stream = file.OpenReadStream(); await block.UploadFromStreamAsync(stream); } } var queueMail = new QueueMail { From = from[0], To = to[0], Subject = subject[0], Body = body[0], AttachedBlobNames = blobNames.ToArray() }; await Queue.Value.CreateIfNotExistsAsync(); var json = JsonConvert.SerializeObject(queueMail); var message = new CloudQueueMessage(json); await Queue.Value.AddMessageAsync(message); return(new OkObjectResult($"Enqueue mail success.")); }