How to tell when Sendgrid's DeliverAsync is done (vb.net) - vb.net

I'm working with Sendgrid to send out emails Async (in vb.net) and want to notify the user when the process is complete. What's the fastest/easiest way to do this? I'm still new to threads and don't know how to wait on a sendgrid task/thread to finish.
Thanks

You should be able to use the Await keyword, to cause the cause execution to stop until the message has been sent to SendGrid:
Dim response = Await YourAsyncDeliveryFunction(email)
' Do what you want
However, sending a message to SendGrid does not mean that it's in the user's inbox. The email still needs to be processed by SendGrid, sent to the user's email service provider, which in turn needs to process it and provide that to the user. So, it's near impossible to tell a user when an email is actually in their inbox. Most people just opt to tell users that they should receive an email shortly.

Related

discordGo guildUpdate

When guildUpdate is detected when updated with a server.
with discordGo
I want my bot to send a message to a channel. So when an authorized person makes changes to the server, I want a message to be sent to a particular channel only once, how can I do that?
Its logic is like an invitation bot. Instead of sending a message when the member logs in, it will only send a notification to a channel when the server is edited (updated). But I don't know as I am new to this coding language. :(

Send and Save specific emails. Not a sentitem event listener

Edit: I am just going to use an eventlistener. I would delete the post but maybe somebody will find a non eventlistener way to save a sent mailitem before it is received in the sent item inbox.
Issue: Outlook won't receive VBA sent emails until macro completes. If I use wait, sleep, while loops or anything else, the email will not be received. I can't use a Sent Items event listener because I only want specific emails saved to the folder, not all. I individually know how to save from sent items, I know how to send messages. The issue is the delay between sending the email with VBA and it appearing in my Sent Items box. If I saveas before waiting, the email that is saved is the previous email, but if you try to wait, the sent items folder never updates. Any ideas or simple solutions. I might just be dumb.
I have read every forum but haven't found a solution, I had it running at another company but no longer remember how. I use a macro to send very specific emails and do lots of other tasks. I would then like to grab the email I just sent and save it to a folder using vba. The issue is receiving the email in my "Sent Items" folder is delayed. If I try to capture it or wait to receive it, my code never finishes. All solutions I see in the forums are a Sent Item listener / Inbox event listeners, but I don't need that, I know which emails to trigger it on.
One way or another, you'd need to wait for some event to fire, be that Items.ItemAdd on the Sent Items folder, or SyncObject.SyncEnd on the SyncObject - message submission is asynchronous, so no amount of sleep or while loops would help you. You cannot just stop your VBA script and resume it when the message is actually sent since your code is running on the main Outlook thread - if your script pauses, so does Outlook.
You can try using the NameSpace.SendAndReceive method which initiates immediate delivery of all undelivered messages submitted in the current session, and immediate receipt of mail for all accounts in the current profile. Note, calling the SendAndReceive method is asynchronous. SendAndReceive provides the programmatic equivalent to the Send/Receive All command that is available when you click Tools and then Send/Receive.
If you don't need to synchronize all objects, you can use the SyncObjects collection object to select specific objects. For more information, see NameSpace.SyncObjects.
In your VBA code you may also consider using the DoEvents function which yields execution so that the operating system can process other events. DoEvents passes control to the operating system. Control is returned after the operating system has finished processing the events in its queue and all keys in the SendKeys queue have been sent (if any).
DoEvents is most useful for simple things like allowing a user to cancel a process after it has started, for example a search for a file.
Solution, not the solution or used in the past but I settled.
Basically just the event listener solution that everyone in all the forums suggest. I created a separate folder in my Sent Items and use myNameSpace.GetDefaultFolder to set that folder for the VBA sent items.. I send the emails only to that folder and I added the listener to only that folder. This allows me to separate the Sent items and this specific VBA sent emails and then to save them automatically. I am still looking for a way to save the sent Mail Item before the Sent Item Inbox shows it, but I have given up at this point. Thanks for everyone's help. If I find the better answer, I will try to post it along with the code.

Event sourcing combinded with deletable data

I want to develop an Emailer microservice which provides a SendEmail command. Inside the microservice I have an aggregate in mind which represents the whole email process with the following events:
Aggregate Email:
(EmailCreated)
EmailDeliveryStarted
EmailDeliveryFailed
EmailRecipientDelivered when one of the recipients received the email
EmailRecipientDeliveryFailed when one of the recipients could not receive the email
etc.
In the background the email delivery service SendGrid is used; my microservice works like a facade for that with my own events. The incoming webhooks from SendGrid are translated to proper domain events.
The process would look like this:
Command SendEmail ==> EmailCreated
EmailCreatedHandler ==> Email.Send (to SendGrid)
Incoming webhook ==> EmailDeliveryStarted
Further webhooks ==> EmailRecipientDelivered, EmailRecipientDeliveryFailed, etc.
Of course if I'd want to replace the external webservice and it would apply other messaging strategies I would adapt to that but keep my domain model with it's events. I want to let the client not worry about the concrete email delivery strategy.
Now the crucial problem I face: I want to accept the SendEmail commands even if SendGrid is not available at that very moment, which entails storing the whole email data (with attachments) and then, with an event handler, start the sending process. On the other hand I don't want to bloat my initial EmailCreated event with this BLOB data. And I want to be able to clean up this data after SendGrid has accepted my send email request.
I could also try both sending the email to SendGrid and storing an initial EmailDeliveryStarted event in the SendEmail command. But this feels like a two-phase commit: if SendGrid accepted my call but somehow my repository was unable to store the EmailDeliveryStarted event the client would be informed that something went wrong and it tries again which would be a disaster.
So I don't know how to design my aggregate and, more important, my EmailCreated event since it should not contain the BLOB data like attachments.
I found this question interesting and it took a little bit to reflect on that.
First things first - I do not see an obligation to store the email attachments in the event. You can simply store the fully qualified name of the files attached. That would keep the event log smaller and perhaps rule out the need for "deleting" the event (and you know that, in an event source model, you should not do that).
Secondly, assuming that the project is not building an e-mail client, I don't see a need to model an e-mail as an aggregate root. I see AggregateRoots represent business-relevant domains, not for a utility task like sending an e-mail. You could model this far more easily using a database table / document that keeps track of what has been sent and what not yet. I see sending e-mails through SendGrid as a reaction to a business event, certainly to be tracked, but not an AggregateRoot in its own right.
Lastly, if you want to accept SendEmail commands also when SendGrid is offline, the aggregate emits an EmailQueued event. The EmailQueuedHandler will produce a line on the read model of the process in charge taking all the Emails in queued state and batch them for sending. If the communication with SendGrid fails, you can either:
Do nothing, the sender process will pick the email at the next attempt
Emit a EmailSendFailed, intercepted by a Handler that will increase the retry count (if you want to stop after a number of retries).
Hope that is sufficiently clear and best of luck with your project.

Sending Email vb.Net Stoping program

I need help to make Visual Basic not stop while sending emails.
I am using Smtp_Server.Send(e_mail) everytime it's sends an email the program stops for 5 seconds and then it's stop work for maybe 3 sec and then it sends the mail.
I want to be able to still use the program while it's sends the mail Help plz!
You can use some logging or careful observation in the debugger to confirm, but the conversation between your client and the SMTP server is probably taking 5 seconds (which is quite long, but plausible).
The solution is to use multiple threads to send email.
If you are sending batches of emails, try starting with 5-10 threads (with too many, the SMTP server on the other end might start rejecting some connection attempts).
If you are trying to send a single email at a time, but it is blocking your main application, you can use a single separate thread to perform the send.

Re-getting POP3 messages

I am using Peter Huber's POP3 client to connect to gmail and download messages.
The inboxes being accessed are transactional inboxes used only for code-access. That is, a message comes in with a order file attached, code will process it and then delete the message. One stipulation of the code though was a DEBUG flag, which if set would prevent the code from deleting the message so that you can run the program again later without the debug flag and reprocess the message. So, in my code I have
If Not Arguments.Debug Then pop.DeleteEmail(eid)
This works fine. Problem is, even when not deleting the message, running the program a second time will not re-retrieve the message, even though if I login to gmail and look at the inbox, it is still there. The only way I can get the program to see the message again is to forward the message back to the same inbox. But in Peter's code I do not see anywhere where he is keeping track of seen messages between sessions.
Is this something that is done on gmail's end? Refusing to deliver a message to the same client a second time? If so, is there any way I can change my gmail account so that it will always show all messages in the inbox to a client when retrieving the list of messages, even ones already "seen"? I don't see anything in the gmail settings screen.
UPDATE: I tried adding a method to send a RSET command to the server, as per this comment on the codeproject page. I then call my new Reset() method after retrieving my messages but before disconnecting, ... but I still have the same problem.
Okay... found a "sort of" answer after reading through pages of the comments on the codeproject project.
According to this comment, the RSET command does not actually do anything when you are dealing with gmail's servers.
The "answer" is to prepend your username with the string "recent:", so instead of logging in with [myaccount#gmail.com] you log in with [recent:myaccount#gmail.com]. Rather hackish, ... but it works.