I am writing a newsletter application using CDO.Message. But get an error back that we have to many connections. Seems they have a limit of 10 simultaneous connections.
So, is there a way to send several messages on one connection, or disconnect faster?
There is a cdo/configuration/smtpconnectiontimeout parameter, but I think that's more about how long the sender will try.
(If we send,ant it fails, it will succeed again after some minutes, probably meaning that the connection is disconnected).
(We are using CDO partly because we are pulling the HTML message body from a webserver)
Edit:
Public Sub ipSendMail(ByVal toEmail As String, ByVal fromEmail As String, ByVal subject As String, ByVal url As String)
Dim iMsg As Object
Set iMsg = CreateObject("CDO.Message")
iMsg.From = fromEmail
iMsg.To = toEmail
iMsg.Subject = subject
iMsg.CreateMHTMLBody(url)
iMsg.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
iMsg.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "relay.wwwwwwwwww.net"
iMsg.Configuration.Fields.Item_
("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
iMsg.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout") = 0
iMsg.Configuration.Fields.Update()
iMsg.Send()
Set iMsg = Nothing
End Sub
Try to use SMTP instead of CDO, System.Web.Mail.SmtpMail
You could implement a queue, that is processed by a background thread. The background thread would only send one message at a time.
You can store the email in a database table, which is processed by a scheduled task or a stored procedure. Those can again send one mail at a time, and have the advantage of being able to retry, if it goes wrong.
Ordinarily you only need one connection regardless of how many messages you are sending.
Perhaps you are not releasing something that you should be.
Edit: Just a thought, the SMTP server you are sending to, it wouldn't happen to be host on an XP box perhaps for testing reasons?
Edit: Ok so your SMTP server is fine.
What platform is the server supplying the result of the URL?
I know that CDO can be quirky at times, so these are the possible suggestions that I would make:
A queue would probably work the best for you. After that, I would consider setting up a local SMTP server without inbound connection limits that uses a smarthost to queue up your outbound messages. (This could actually be written fairly easily. The "S" is for "Simple" and it actually is.)
If all else fails... You could always roll your own mailer component implementing RFCs 2821 and 2822 (or whatever the latest and greatest RFCs are for SMTP and message format)
EDIT: If the newsletter you are sending out is identical for all recipients, you can address it to a dummy recipient (i.e. newsletter#yourdomain.com) and BCC it to the recipient list (or a subset of the recipient list). Just be careful not to get flagged as unsolicited commercial email. Let your provider know what you are doing. They have to deal with the complaints, and you are the one paying the bill. Letting them know that complaints would be mostly unwarranted (and few and far between) will help to assuage their natural risk aversion.
Related
I made a software couple years ago using VB6 that works as a TCP server, receives multiple connections from clients.
The basic Idea of the software is to listen on a specific port, accept connections from different clients and pass each connection to a separate winsock which analyzes the data, looks in DB, replies with the proper message, and then closes the connection.
Here's some code:
Initializing the sockets when the application starts:
For i = 1 To MaxCon
Load sckAccept(i)
Next i
sckListen.Listen
Accepting connections:
Private Sub sckListen_ConnectionRequest(ByVal requestID As Long)
Dim aFreeSocket As Integer
aFreeSocket = GetFreeSocket
If aFreeSocket = 0 Then
sckAccept(0).Accept requestID
sckAccept(0).SendData "Server is full!"
sckAccept(0).Close
Else
sckAccept(aFreeSocket).Accept requestID
End Sub
Receiving data, analyzing it, and reply:
Private Sub sckAccept_DataArrival(Index As Integer, ByVal bytesTotal As Long)
Dim sData As String
sckAccept(Index).GetData sData
'Do lots of analyizing and search in DB
'
'
sckAccept(Index).SendData "Message"
'
'
DoEvents
sckAccept(Index).Close
End Sub
Everything was working fine, but now the number of connections has increased (couple dozens per second), so the software started getting Out of stack space exception (because of DoEvents).
I know that in many cases DoEvents is evil, but if I remove it, the application UI won't respond (because of the over load on the thread) and some data might not be delivered.
So, my question is: does anyone have an idea of how to get around this problem with/without using DoEvents?
Note: I know that VB6 doesn't really support multi-threading and might be a PITA for such situations. I'm actually planning to upgrade the software and re-create it using .Net, but that will take some time. That's why I need to fix this problem in VB6 since the software is written in VB6 for now.
Well, I managed to figure out the problem, and have solved it.
The short answer
Do NOT use DoEvents.. Some data won't be delivered? Well, close the connection ONLY in the SendComplete event.
The long answer
First thing first:
Why I used DoEvents in the first place? because some of the sent messages were not being delivered. A lot of articles/questions on the internet suggest using DoEvents after Socket.SendData in order to guarantee the data arrival to the receiver.
I digged deeper into this trying to figure out why the messages aren't delivered. I found out that this problem only occurs when closing the connection after sending the message:
Socket.SendData "Message"
'
'
Socket.Close
So, I simply moved the line that closes the connection to the SendComplete event, removed the DoEvents sentence -since I don't need it anymore-, and the problem is gone :)
Private Sub sckAccept_SendComplete(Index As Integer)
sckAccept_Close (Index)
End Sub
I hope this could help someone who has the same problem.
If I have multiple processes and am using socket.io-redis, when I do io.to(room).emit(namespace, message); is this handled seamlessly and efficiently? Or am I misunderstanding socket.io-redis's role?
Hi in short as far as I know about this is-
io.to('room').emit('namespace', 'message');
Means, sending message named 'namespace' with value 'message' to all clients in 'room' channel, including sender.
Detail info (found in here)-
// send to current request socket client
socket.emit('message', "this is a test");// Hasn't changed
// sending to all clients, include sender
io.sockets.emit('message', "this is a test"); // Old way, still compatible
io.emit('message', 'this is a test');// New way, works only in 1.x
// sending to all clients except sender
socket.broadcast.emit('message', "this is a test");// Hasn't changed
// sending to all clients in 'game' room(channel) except sender
socket.broadcast.to('game').emit('message', 'nice game');// Hasn't changed
// sending to all clients in 'game' room(channel), include sender
io.sockets.in('game').emit('message', 'cool game');// Old way, DOES NOT WORK ANYMORE
io.in('game').emit('message', 'cool game');// New way
io.to('game').emit('message', 'cool game');// New way, "in" or "to" are the exact same: "And then simply use to or in (they are the same) when broadcasting or emitting:" from http://socket.io/docs/rooms-and-namespaces/
// sending to individual socketid, socketid is like a room
io.sockets.socket(socketid).emit('message', 'for your eyes only');// Old way, DOES NOT WORK ANYMORE
socket.broadcast.to(socketid).emit('message', 'for your eyes only');// New way
Even more can be found here.
Basic-
Actually the thing is your question is so sort that it is very difficult for others to understand what u exactly need. So, I assume u need to know basic concepts behind this also. So I am adding this part also for your kind info.
The concept here with socket.io with Redis is u should manage connection with socket and store the data in redis as DB.
Redis normally used for applying a layer upon DB (or caching database) so that some data can be stored for a time interval. So between that time, if any query is needed, data will come from Redis, not from DB query.
This system is applied for performance tuning so that your system can handle a huge load at the same time.
In your case, u can cache data for a short time interval for sending the messages through socket.io.
More can be found here-
http://notjoshmiller.com/socket-io-rooms-and-redis/
http://goldfirestudios.com/blog/136/Horizontally-Scaling-Node.js-and-WebSockets-with-Redis
https://github.com/socketio/socket.io-redis/issues/98
Think this answer will surely help u.
I want to process a bunch of my emails with Net::IMAP, but I want to skip the ones with attachments because they take too long. Any hints? Ultimately, I'm looking to download all the text and HTML content of emails, as fast as possible. Right now, I'm fetching one UID at a time, and parallelizing it with 15 processes (the max GMAIL allows), but I'm hitting a snag on the messages with attachments.
imap = Net::IMAP.new('imap.gmail.com', 993, usessl = true, certs = nil, verify = false)
imap.authenticate('XOAUTH2', user.email, user.token)
mailbox = "[Gmail]/All Mail"
imap.select(mailbox)
message_id = 177
imap.fetch(message_id,'RFC822')[0].attr['RFC822'] # this fetches the whole message, including attachment, which makes it slow...
imap rfc does not provide any such implementations but as an alternative there could be a possible hack, assuming that the mail is following the rfc standard, fetch the entire mail header of mail and check for content type if it is multipart/mixed then for sure an attachment exists in a mail.
On content type you can get more info at http://en.wikipedia.org/wiki/MIME
This is just one of possible ways to find an attachment.
Here's what I'm attempting to do: Let's assume that you are in mail and create a New blank mail message, then enter some data into it, such as body copy, etc. (in my case, the message was created through scripting bridge using the "Mail Contents of this Page" from safari... the main purpose of this process for my application.)
From my application, I want to select that message and assign it to:
MailOutgoingMessage *myMessage;
so that I can programmatically add recipients. I've tried several ways of doing this which seemed logical, but so far I haven't found the right combination, and the header file doesn't seem to be very clear to me (I'm new to scripting bridge.)
My initial thought was to try this:
mailMessage = [[mail outgoingMessages] lastObject];
Which should grab the last outgoing message created. It seems to work in that I am able to add recipients to mailMessage (though there have been a few times that I received unexpected results when multiple outgoing messages exist, such as adding the recipients to the wrong message) but attempting to log the subject line of the message:
NSLog(#"Subject = %#",[mailMessage subject]);
always returns NULL even though there is a subject clearly viewable in the subject field of the message. NULL is returned for any other parameter as well.
I'm gathering it must be a problem with my assignment to mailMessage above, because the only time I receive a NULL for message properties (or receive unexpected results) is if I try to point mailMessage to an existing outgoing message. If I create the mail message with scripting bridge, then I can retrieve all of the properties correctly.
Does anyone understand the hierarchy of the Mail scripting enough to tell me why I am getting NULLs for the parameters using the above assignment for mailMessage? What would the simplest way be go grab my message so that I can add recipients and later call the:
[myMessage send];
method? Any insight would be helpful. I've spent a week going through the mail.h header file and am quite literally at a loss as to what else to try at this point.
There's no way to (send, get or set the properties of the outgoing message) that the user or Safari has created.
It's a bug (it stopped working since Mac OS X 10.4), or some privacy/security considerations.
I have a sender, a message forwarder which sends fix sizes of byte data at a rate of 5 milliseconds per message to my receiving program written in vb6, when I run the message fowarder and my receiving program on one machine, there's no issue but when they run on separate machines, the receiving program starts to experience some abnormalities.
e.g:
private sub socket_DataArrival(index as integer, ByVal dataTotal as Long)
Dim Data() as Byte
Length.Text = dataTotal
socket.GetData byteData, vbArray + vbByte
If Length.Text = "100" Then
txtOutput.Text = "Message1"
ElseIf Length.Text = "150" Then
txtOutput.text = "Message2"
End Sub
I will sometimes receive "2 in 1" message as in it comes in as 250 bytes or a non-recognizable byte size when I should be receiving either 100 or 150 only but if I reduce the sending rate to a slower speed say 50 milliseconds per message then it will be fine.
Can anyone provide with an advice? Thanks.
When sending data over a network you have to get used to the fact that the packets may arrive out of order, not promptly, not at all, etc.
You need to improve your message protocol to include a header that states which type of message follows. If order is important include a sequence number (I'm assuming you're using UDP). At present you are relying on timing to separate messages, which you cannot rely on over a network.
Buffer all your arriving data and handle it in chunks - the header allows you to tell what chunk size to use. Separate your input buffering from your message handling - use the DataArrival event to add data to the buffer, use a Timer or some other means of polling the buffer to check if it has messages ready to parse. Alas, this is VB6 so threading is not so easy. Take a look at The Common Controls Replacement Project timer object DLL if you need a Timer class that doesn't rely on a UI element being present.