Limit outbound mails by user, domain or server average
Limit outbound mails by user, domain or server average
MODERATOR EDIT: An updated version of the script below featuring fixes, improvements and file locking handling is available here: http://www.hmailserver.com/forum/viewto ... 20&t=28269
This script limits the outbound emails either by user account or by domain. It also calculates an average over the last x days and when the total amount of outbound emails reaches a defined level the mail is also blocked.
The primary reason for this script is the higher security. If one or some account gets hacked the damage is limited, at least I use the script therefore.
How does user or domain limits work?
You define a general user and domain limit. In a separate file you can also define exceptions for users or domain. The script counts every mail and if the amount reaches the limit a message will be send and the mail will be rejected. You can also define a warning level, when an email is send saying the limits will be reached soon. These mails can be send to the admin or the user.
How does server average limit work?
The script counts the outbound mail of the server and calculates an average over the last x days. When the server passes a threshold factor, let's say 5 times more than the average over the last 20 days the script rejects the mail. An email is send to the admin, also when a warning level is reached.
Have used it the last 20 days and works fine. Installation manual and script itself is in the zip.
version2: tiny error- missing "end sub" at the end of sub outgoing_limitations_send_message
version3: bugfix - outgoingstore file was created with the wrong data positions
version4: instability fix: Division 0 in the average calculation
version5: support of default domains
This script limits the outbound emails either by user account or by domain. It also calculates an average over the last x days and when the total amount of outbound emails reaches a defined level the mail is also blocked.
The primary reason for this script is the higher security. If one or some account gets hacked the damage is limited, at least I use the script therefore.
How does user or domain limits work?
You define a general user and domain limit. In a separate file you can also define exceptions for users or domain. The script counts every mail and if the amount reaches the limit a message will be send and the mail will be rejected. You can also define a warning level, when an email is send saying the limits will be reached soon. These mails can be send to the admin or the user.
How does server average limit work?
The script counts the outbound mail of the server and calculates an average over the last x days. When the server passes a threshold factor, let's say 5 times more than the average over the last 20 days the script rejects the mail. An email is send to the admin, also when a warning level is reached.
Have used it the last 20 days and works fine. Installation manual and script itself is in the zip.
version2: tiny error- missing "end sub" at the end of sub outgoing_limitations_send_message
version3: bugfix - outgoingstore file was created with the wrong data positions
version4: instability fix: Division 0 in the average calculation
version5: support of default domains
- Attachments
-
- limitsmtp_v5_version5.zip
- (5.2 KiB) Downloaded 3055 times
Last edited by andyp on 2009-03-14 09:20, edited 9 times in total.
Re: Limit outbound mails by user, domain or server average
Very useful, but I did not understood something.
The limit for user/domain is per day?
The limit for user/domain is per day?
Re: Limit outbound mails by user, domain or server average
Yes, both user/domain and average.
Re: Limit outbound mails by user, domain or server average
This is very useful code. But I couldn't load it
When the code is loaded, the outboundstore.txt and outboundexceptions.txt files are created. The first record is created in the outboundstore.txt file... Then, nothing happens, no more record is added to the file.
The view of the file:
# SMTP outgoing storage
39847 ali.veli@remed.com.tr 1
39847 @remed.com.tr 1
outboundstoreavg.txt is not created.
And the logs are below.
"03.02.2009 23:20:01" " User has authenticated. User ali.veli@remed.com.tr, Client 88.239.39.30"
"03.02.2009 23:20:01" " SMTP outgoing limitations"
"03.02.2009 23:20:01" " Number of recipients 1"
"03.02.2009 23:20:01" " Reading exceptions file C:\MailServer\Events\outboundexceptions.txt"
"03.02.2009 23:20:01" " Reading storage file C:\MailServer\Events\outboundstore.txt"
"03.02.2009 23:20:02" " User has authenticated. User ali.veli@remed.com.tr, Client 88.239.39.30"
"03.02.2009 23:20:02" " SMTP outgoing limitations"
"03.02.2009 23:20:02" " Number of recipients 1"
"03.02.2009 23:20:02" " Reading exceptions file C:\MailServer\Events\outboundexceptions.txt"
"03.02.2009 23:20:02" " Reading storage file C:\MailServer\Events\outboundstore.txt"
"03.02.2009 23:20:03" " User has authenticated. User ali.veli@remed.com.tr, Client 88.239.39.30"
"03.02.2009 23:20:03" " SMTP outgoing limitations"
"03.02.2009 23:20:03" " Number of recipients 1"
"03.02.2009 23:20:03" " Reading exceptions file C:\MailServer\Events\outboundexceptions.txt"
"03.02.2009 23:20:03" " Reading storage file C:\MailServer\Events\outboundstore.txt"

The view of the file:
# SMTP outgoing storage
39847 ali.veli@remed.com.tr 1
39847 @remed.com.tr 1
outboundstoreavg.txt is not created.
And the logs are below.
"03.02.2009 23:20:01" " User has authenticated. User ali.veli@remed.com.tr, Client 88.239.39.30"
"03.02.2009 23:20:01" " SMTP outgoing limitations"
"03.02.2009 23:20:01" " Number of recipients 1"
"03.02.2009 23:20:01" " Reading exceptions file C:\MailServer\Events\outboundexceptions.txt"
"03.02.2009 23:20:01" " Reading storage file C:\MailServer\Events\outboundstore.txt"
"03.02.2009 23:20:02" " User has authenticated. User ali.veli@remed.com.tr, Client 88.239.39.30"
"03.02.2009 23:20:02" " SMTP outgoing limitations"
"03.02.2009 23:20:02" " Number of recipients 1"
"03.02.2009 23:20:02" " Reading exceptions file C:\MailServer\Events\outboundexceptions.txt"
"03.02.2009 23:20:02" " Reading storage file C:\MailServer\Events\outboundstore.txt"
"03.02.2009 23:20:03" " User has authenticated. User ali.veli@remed.com.tr, Client 88.239.39.30"
"03.02.2009 23:20:03" " SMTP outgoing limitations"
"03.02.2009 23:20:03" " Number of recipients 1"
"03.02.2009 23:20:03" " Reading exceptions file C:\MailServer\Events\outboundexceptions.txt"
"03.02.2009 23:20:03" " Reading storage file C:\MailServer\Events\outboundstore.txt"
Re: Limit outbound mails by user, domain or server average
outboundstoreavg.txt is only created when the server avg limits activates. So when you reach the warning level or the limit the script stores the date and the kind (Warning / Limit Reached) to avoid sending a lot of msgs to the admin.
My outboundstore.txt looks different. Have you change something in the script?
Usually the amount of emails is before the email or domain!!!
My outboundstore.txt looks different. Have you change something in the script?
Usually the amount of emails is before the email or domain!!!
Re: Limit outbound mails by user, domain or server average
There is an error on line 437. "End Sub" tag is forgotten. I have just corrected this. I didn't change anywhere in your code. You can see my public settings:
Public obApp
Public domain_buffer
Public Const ipslocalhost = "0.0.0.0" 'separated by #
Public Const user = "Administrator"
Public Const pw = "xxxxxxxxxxx"
Public Const logspath = "C:\MailServer\Events\" 'ends with a backslash
Public Const write_log_active = true
'User and Domain outgoing limitation
Public Const outgoingstore = "C:\MailServer\Events\outboundstore.txt"
Public Const outgoingexceptions = "C:\MailServer\Events\outboundexceptions.txt"
Public Const outgoingstoreavg = "C:\MailServer\Events\outboundstoreavg.txt"
Public Const max_emails_per_user = 100
Public Const max_emails_per_domain = 300
Public Const warning_factor = 0.8
Public Const server_average_days = 20 ' 0 will deactivate
Public Const server_average_threshold_factor = 10
Public Const warning_factor_avg = 0.6
Public Const msg_admin_warning = True
Public Const msg_admin_passed = True
Public Const msg_user_warning = True
Public Const msg_user_passed = True
Public Const msg_from = "Admin <admin@remed.com.tr>"
Public Const msg_fromaddress = "admin@remed.com.tr"
Public obApp
Public domain_buffer
Public Const ipslocalhost = "0.0.0.0" 'separated by #
Public Const user = "Administrator"
Public Const pw = "xxxxxxxxxxx"
Public Const logspath = "C:\MailServer\Events\" 'ends with a backslash
Public Const write_log_active = true
'User and Domain outgoing limitation
Public Const outgoingstore = "C:\MailServer\Events\outboundstore.txt"
Public Const outgoingexceptions = "C:\MailServer\Events\outboundexceptions.txt"
Public Const outgoingstoreavg = "C:\MailServer\Events\outboundstoreavg.txt"
Public Const max_emails_per_user = 100
Public Const max_emails_per_domain = 300
Public Const warning_factor = 0.8
Public Const server_average_days = 20 ' 0 will deactivate
Public Const server_average_threshold_factor = 10
Public Const warning_factor_avg = 0.6
Public Const msg_admin_warning = True
Public Const msg_admin_passed = True
Public Const msg_user_warning = True
Public Const msg_user_passed = True
Public Const msg_from = "Admin <admin@remed.com.tr>"
Public Const msg_fromaddress = "admin@remed.com.tr"
Re: Limit outbound mails by user, domain or server average
Hi There,
I just install version 2 of the script and this VB error is shown in the hmalserver error log:
"ERROR" 676 "2009-02-18 14:52:24.547" "Script Error: Source: Microsoft VBScript runtime error - Error: 800A000D - Description: Type mismatch: 'CLng' - Line: 229 Column: 6 - Code: (null)"
"ERROR" 3068 "2009-02-18 14:57:26.906" "Script Error: Source: Microsoft VBScript runtime error - Error: 800A000D - Description: Type mismatch: 'CLng' - Line: 229 Column: 6 - Code: (null)"
Is there issue with script itself?
Jozef
I just install version 2 of the script and this VB error is shown in the hmalserver error log:
"ERROR" 676 "2009-02-18 14:52:24.547" "Script Error: Source: Microsoft VBScript runtime error - Error: 800A000D - Description: Type mismatch: 'CLng' - Line: 229 Column: 6 - Code: (null)"
"ERROR" 3068 "2009-02-18 14:57:26.906" "Script Error: Source: Microsoft VBScript runtime error - Error: 800A000D - Description: Type mismatch: 'CLng' - Line: 229 Column: 6 - Code: (null)"
Is there issue with script itself?
Jozef
Re: Limit outbound mails by user, domain or server average
Another user has a similar problem. That's odd.
After the line (about Nr. 147) ln = f.ReadLine could you add a line with write_log(ln), now every line in the storage is written in the log. Could you post me the output in the log, when the error happens.
After the line (about Nr. 147) ln = f.ReadLine could you add a line with write_log(ln), now every line in the storage is written in the log. Could you post me the output in the log, when the error happens.
Re: Limit outbound mails by user, domain or server average
Hi,
I put that writeln and this is the total output:
"2/19/2009 4:00:05 PM" " User has authenticated. User jozef.balaz@smahu.com, Client 127.0.0.1"
"2/19/2009 4:00:05 PM" " SMTP outgoing limitations"
"2/19/2009 4:00:05 PM" " Number of recipients 1"
"2/19/2009 4:00:05 PM" " Reading exceptions file D:\Data\Logs\hMailServer events\outboundexceptions.txt"
"2/19/2009 4:00:05 PM" " Reading storage file D:\Data\Logs\hMailServer events\outboundstore.txt"
"2/19/2009 4:00:05 PM" "# SMTP outgoing storage"
"2/19/2009 4:00:05 PM" ""
"2/19/2009 4:00:05 PM" "39862 jozef.balaz@smahu.com 1"
this is hmailserver error log:
"ERROR" 4560 "2009-02-19 16:00:05.435" "Script Error: Source: Microsoft VBScript runtime error - Error: 800A000D - Description: Type mismatch: 'CLng' - Line: 230 Column: 6 - Code: (null)"
Thanks a lot for your support
Jozef
I put that writeln and this is the total output:
"2/19/2009 4:00:05 PM" " User has authenticated. User jozef.balaz@smahu.com, Client 127.0.0.1"
"2/19/2009 4:00:05 PM" " SMTP outgoing limitations"
"2/19/2009 4:00:05 PM" " Number of recipients 1"
"2/19/2009 4:00:05 PM" " Reading exceptions file D:\Data\Logs\hMailServer events\outboundexceptions.txt"
"2/19/2009 4:00:05 PM" " Reading storage file D:\Data\Logs\hMailServer events\outboundstore.txt"
"2/19/2009 4:00:05 PM" "# SMTP outgoing storage"
"2/19/2009 4:00:05 PM" ""
"2/19/2009 4:00:05 PM" "39862 jozef.balaz@smahu.com 1"
this is hmailserver error log:
"ERROR" 4560 "2009-02-19 16:00:05.435" "Script Error: Source: Microsoft VBScript runtime error - Error: 800A000D - Description: Type mismatch: 'CLng' - Line: 230 Column: 6 - Code: (null)"
Thanks a lot for your support
Jozef
Re: Limit outbound mails by user, domain or server average
OK, this was a true bug. Posted the fixed code above.
Re: Limit outbound mails by user, domain or server average
Hello AndyP,
thanks for patch. I can now see that users are stored in the file but now in the hmailserver error log, new error is shown:
"ERROR" 2416 "2009-02-20 10:43:37.875" "Script Error: Source: Microsoft VBScript runtime error - Error: 800A0006 - Description: Overflow - Line: 262 Column: 1 - Code: (null)"
"ERROR" 2428 "2009-02-20 10:44:37.412" "Script Error: Source: Microsoft VBScript runtime error - Error: 800A0006 - Description: Overflow - Line: 262 Column: 1 - Code: (null)"
Note: I follow update instructions and I delete all files and overwrite procedure as it is described in your document.
Can you please take a look?
Thanks for your great support.
Jozef
thanks for patch. I can now see that users are stored in the file but now in the hmailserver error log, new error is shown:
"ERROR" 2416 "2009-02-20 10:43:37.875" "Script Error: Source: Microsoft VBScript runtime error - Error: 800A0006 - Description: Overflow - Line: 262 Column: 1 - Code: (null)"
"ERROR" 2428 "2009-02-20 10:44:37.412" "Script Error: Source: Microsoft VBScript runtime error - Error: 800A0006 - Description: Overflow - Line: 262 Column: 1 - Code: (null)"
Note: I follow update instructions and I delete all files and overwrite procedure as it is described in your document.
Can you please take a look?
Thanks for your great support.
Jozef
Re: Limit outbound mails by user, domain or server average
Please add a line containing write_log("toindex = " & toindex) after line toindex = idt - minday and post me the log.
Re: Limit outbound mails by user, domain or server average
This is the result:
"2/20/2009 12:26:37 PM" " User has authenticated. User jozef.balaz@smahu.com, Client 127.0.0.1"
"2/20/2009 12:26:37 PM" " SMTP outgoing limitations"
"2/20/2009 12:26:37 PM" " Number of recipients 1"
"2/20/2009 12:26:37 PM" " Reading exceptions file D:\Data\Logs\hMailServer events\outboundexceptions.txt"
"2/20/2009 12:26:37 PM" " Reading storage file D:\Data\Logs\hMailServer events\outboundstore.txt"
"2/20/2009 12:26:37 PM" " adding to line 39864 3 @smahu.com"
"2/20/2009 12:26:37 PM" " adding to line 39864 2 jozef.balaz@smahu.com"
"2/20/2009 12:26:37 PM" "toindex = 0"
Jozef
"2/20/2009 12:26:37 PM" " User has authenticated. User jozef.balaz@smahu.com, Client 127.0.0.1"
"2/20/2009 12:26:37 PM" " SMTP outgoing limitations"
"2/20/2009 12:26:37 PM" " Number of recipients 1"
"2/20/2009 12:26:37 PM" " Reading exceptions file D:\Data\Logs\hMailServer events\outboundexceptions.txt"
"2/20/2009 12:26:37 PM" " Reading storage file D:\Data\Logs\hMailServer events\outboundstore.txt"
"2/20/2009 12:26:37 PM" " adding to line 39864 3 @smahu.com"
"2/20/2009 12:26:37 PM" " adding to line 39864 2 jozef.balaz@smahu.com"
"2/20/2009 12:26:37 PM" "toindex = 0"
Jozef
Re: Limit outbound mails by user, domain or server average
OK, we should have it. Replace the provided functions please. Delete the outgoingstore file again.
- Attachments
-
- new functions.zip
- (2 KiB) Downloaded 1108 times
Re: Limit outbound mails by user, domain or server average
Hello AndyP
Thanks a lot. It seems that everything is working perfectly
Jozef
Thanks a lot. It seems that everything is working perfectly
Jozef
Re: Limit outbound mails by user, domain or server average
I am wondering why you are the first one complaining. This script should have never worked. I increased the functionality day per day with a already existing store file. So I never had this error. 

Re: Limit outbound mails by user, domain or server average
Hello AndyP
Great job! I have tested the script in my system and it worked perfectly.
There is just a specific case that might be checked: user sends mail by default domain (setting up in Advanced tab).
When using default domain for SMTP authentication, users just only type the username instead of the whole email account.
The error found in log file:
Description: Invalid procedure call or argument: 'Mid' - Line: 109 Column: 2 - Code: (null)"
"ERROR" 1884 "2009-02-25 15:35:25.423" "Script Error: Source: Microsoft VBScript runtime error - Error: 800A0005 -
Thank you
Trieu
Great job! I have tested the script in my system and it worked perfectly.
There is just a specific case that might be checked: user sends mail by default domain (setting up in Advanced tab).
When using default domain for SMTP authentication, users just only type the username instead of the whole email account.
The error found in log file:
Description: Invalid procedure call or argument: 'Mid' - Line: 109 Column: 2 - Code: (null)"
"ERROR" 1884 "2009-02-25 15:35:25.423" "Script Error: Source: Microsoft VBScript runtime error - Error: 800A0005 -
Thank you
Trieu
Re: Limit outbound mails by user, domain or server average
Please insert the bold line into the code, then it should work.
If oclient.username <> "" Then
usern = oclient.username
domn = Mid(oclient.username,InStr(1,oclient.username,"@"))
elseif instr(1,oclient.username,"@") = 0 then
usern = oclient.username & "@yourdefaultdomain.com"
domn = "@yourdefaultdomain.com"
ElseIf is_local_domain(omessage.fromaddress) then
usern = omessage.fromaddress
domn = Mid(omessage.fromaddress,InStr(1,omessage.fromaddress,"@"))
Else
usern = "local"
domn = "@local"
End If
I will provide a new version in the next days, which can be better configured using a global variable.
If oclient.username <> "" Then
usern = oclient.username
domn = Mid(oclient.username,InStr(1,oclient.username,"@"))
elseif instr(1,oclient.username,"@") = 0 then
usern = oclient.username & "@yourdefaultdomain.com"
domn = "@yourdefaultdomain.com"
ElseIf is_local_domain(omessage.fromaddress) then
usern = omessage.fromaddress
domn = Mid(omessage.fromaddress,InStr(1,omessage.fromaddress,"@"))
Else
usern = "local"
domn = "@local"
End If
I will provide a new version in the next days, which can be better configured using a global variable.
Re: Limit outbound mails by user, domain or server average
I guess your code mus be change to this for working fine
If oclient.username <> "" Then
usern = oclient.username
If instr(1,oclient.username,"@") = 0 then
usern = oclient.username & "@yourdefaultdomain.com"
domn = "@yourdefaultdomain.com"
Else
domn = Mid(oclient.username,InStr(1,oclient.username,"@"))
End If
ElseIf is_local_domain(omessage.fromaddress) then
usern = omessage.fromaddress
domn = Mid(omessage.fromaddress,InStr(1,omessage.fromaddress,"@"))
Else
usern = "local"
domn = "@local"
End If
If oclient.username <> "" Then
usern = oclient.username
If instr(1,oclient.username,"@") = 0 then
usern = oclient.username & "@yourdefaultdomain.com"
domn = "@yourdefaultdomain.com"
Else
domn = Mid(oclient.username,InStr(1,oclient.username,"@"))
End If
ElseIf is_local_domain(omessage.fromaddress) then
usern = omessage.fromaddress
domn = Mid(omessage.fromaddress,InStr(1,omessage.fromaddress,"@"))
Else
usern = "local"
domn = "@local"
End If
Re: Limit outbound mails by user, domain or server average
ticoi, you are right, of course! 

Re: Limit outbound mails by user, domain or server average
Posted the new script above. Now default domains are supported.
Re: Limit outbound mails by user, domain or server average
Hello andyp,
This is a very handy utility that you have written. Well done!
However, when I try to load the script, no .txt file is created. What could be wrong?
I am using hmailserver 4.
Thanks
This is a very handy utility that you have written. Well done!
However, when I try to load the script, no .txt file is created. What could be wrong?
I am using hmailserver 4.
Thanks
Last edited by bibleman on 2009-04-24 11:40, edited 1 time in total.
Re: Limit outbound mails by user, domain or server average
Check the error log it should tell you what is wrong. If it doesn't make sure the hMail service has permissions to write to wherever the txt file is supposed to be created.
If at first you don't succeed, bomb disposal probably isn't for you! ヅ
Re: Limit outbound mails by user, domain or server average
Hi,
The script appears to be working fine, it is logging events but not preventing over quota users to send e-mails.
"Script Error: Source: Microsoft VBScript runtime error - Error: 800A01B6 - Description: Object doesn't support this property or method: 'oMessage.Recipients(...).OriginalAddress' - Line: 323 Column: 3 - Code: (null)"
The Hmailserver 4 is generating above mentioned error when ever any user exceeds his/her quota but without rejecting outgoing mails.
What could be wrong??
Thanks
The script appears to be working fine, it is logging events but not preventing over quota users to send e-mails.
"Script Error: Source: Microsoft VBScript runtime error - Error: 800A01B6 - Description: Object doesn't support this property or method: 'oMessage.Recipients(...).OriginalAddress' - Line: 323 Column: 3 - Code: (null)"
The Hmailserver 4 is generating above mentioned error when ever any user exceeds his/her quota but without rejecting outgoing mails.
What could be wrong??
Thanks
Re: Limit outbound mails by user, domain or server average
This script is for hMail V5, you are using V4. Perhaps that is the issue.
If at first you don't succeed, bomb disposal probably isn't for you! ヅ
Re: Limit outbound mails by user, domain or server average
This is definetly the issue. Method 'oMessage.Recipients(...).OriginalAddress' doesn't exist in V4. You have to redesign that specific part of the script, to get it running on V4.
Re: Limit outbound mails by user, domain or server average
I dont have knowledge of VBscripting but managed to get it working. If any one interested please let me know i will upload here.
Re: Limit outbound mails by user, domain or server average
Replace
with
This should do the trick.
Code: Select all
If oMessage.FromAddress = emailadmin Then
excptn = true
Else
For k = 0 To oMessage.recipients.count - 1
If oMessage.recipients(k).OriginalAddress = emailadmin Then
excptn = True
End If
Next
End If
Code: Select all
If oMessage.FromAddress = emailadmin Then
excptn = true
If InStr(1," " & oMessage.to,emailadmin ) > 0 Then
excptn = true
Else
For k = 0 To oMessage.recipients.count - 1
If oMessage.recipients(k).Address = emailadmin Then
excptn = True
End If
Next
End If
Re: Limit outbound mails by user, domain or server average
Thanks Andy, i will try it. I had removed same lines to get it working. 

only user-limit control
'------------------------------------------------------------------
' Global variables and settings
'------------------------------------------------------------------
Public obApp
Public domain_buffer
Public Const ipslocalhost = "0.0.0.0" 'separated by #
Public Const user = "Administrator"
Public Const pw = "xXxXx"
Public Const outgoingstore = "E:\hMailServer\Events\Outgoing.txt"
Public Const outgoingexceptions = "E:\hMailServer\Events\Limit.txt"
Public Const date_file = "E:\hMailServer\Events\Limit_Date.txt"
Public Const log_path = "E:\hMailServer\Logs\"
Public Const user_limit = 250
Public Const warning_factor = 0.9
Public Const msg_from = "Deep Design Group <info@ddg.com.tr>"
Public Const msg_fromaddress = "info@ddg.com.tr"
'------------------------------------------------------------------
' Hmailserver Eventhandlers
'------------------------------------------------------------------
Sub OnAcceptMessage(oClient, oMessage)
Result.Value = 0
Set obApp = CreateObject("hMailServer.Application")
Call obApp.Authenticate(user, pw)
If has_client_authenticated(oClient) Then
write_log ("Dogrulandi " & oCLient.username & ", Client " & oClient.IPAddress)
if not check_limit(oClient, oMessage) Then
Result.Message = "Mailserver SMTP outgoing limits."
Result.Value = 2
End if
End if
End Sub
'------------------------------------------------------------------
' SMTP limit outgoing emails of domain and user
'------------------------------------------------------------------
function check_limit(oClient, oMessage)
check_limit = true
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim fs , f
Set fs = CreateObject("scripting.filesystemobject")
Dim idt
Dim content
Dim ln
Dim arr
Dim usern
Dim usernadd
Dim usernnr
Dim user_max
Dim reason
Dim rcptscnt
Dim dayamounts(200)
For i = 0 To 200
dayamounts(i) = 0
Next
Dim pos
Dim minday
minday = 999999
If oclient.username <> "" Then
If instr(1,oclient.username,"@") = 0 Then
usern = oclient.username & "@" & obApp.Settings.DefaultDomain
Else
usern = oclient.username
End If
ElseIf is_local_domain(omessage.fromaddress) then
usern = omessage.fromaddress
Else
usern = "local"
End If
content = "# " & get_date() & " SMTP outgoing storage" & nl & nl
usernadd = true
usernnr = 1
user_max = user_limit
idt = CLng(Date())
rcptscnt = omessage.Recipients.count
write_log("Sayac " & rcptscnt)
write_log(omessage.to)
If fs.FileExists(outgoingexceptions) Then
Set f = fs.OpenTextFile(outgoingexceptions, ForReading)
Do While Not f.AtEndOfStream
ln = f.ReadLine
If ln <> "" And Mid(ln,1,1) <> "#" And Len(ln) > 3 Then
arr = Split(ln,Chr(9))
If UBound(arr) = 1 Then
If arr(0) = usern Then
user_max = CLng(arr(1))
write_log ("Limit " & ln)
End if
Else
write_log ("Limit Basarisiz " & Mid(ln,1,25))
End If
ElseIf Len(ln) > 5 And f.Line > 4 + 1 then
write_log ("Satir Atlandi-1 " & Mid(ln,1,25))
End If
Loop
Else
Set f = fs.OpenTextFile(outgoingexceptions, ForWriting, true)
f.Write("# Outgoing limitation exceptions tab / Chr(9) separated" & nl)
f.Write("# Examples (without # at the beginning)" & nl)
f.Write("# @yourdomain.com 10000" & nl)
f.Write("# address@yourdomain.com 5000" & nl & nl)
f.Close
End If
If fs.FileExists(outgoingstore) Then
Set f = fs.OpenTextFile(outgoingstore, ForReading)
Do While Not f.AtEndOfStream
ln = f.ReadLine
If ln <> "" And Mid(ln,1,1) <> "#" And Len(ln) > 5 Then
arr = Split(ln," ")
If UBound(arr) > 1 Then
If minday > CLng(arr(0)) Then
minday = CLng(arr(0))
End If
End If
If UBound(arr) = 2 Or UBound(arr) = 3 Then
If CLng(arr(0)) = idt And arr(2) = usern Then
usernnr = CLng(arr(1)) + rcptscnt
usernadd = False
write_log ("Eklendi " & ln)
If usernnr > user_max Then
If UBound(arr) = 3 Then
If arr(3) = "X" then
write_log ("Durduruldu")
Else
write_log ("Reddedildi-1")
out_send_message oClient, oMessage, false, usernnr, user_max
End if
Else
write_log ("Reddedildi-2")
out_send_message oClient, oMessage, false, usernnr, user_max
End If
content = content & arr(0) & " " & usernnr & " " & arr(2) & " X" & nl
ElseIf usernnr > user_max * warning_factor then
If UBound(arr) = 3 Then
If arr(3) = "W" then
write_log ("Limit Doldu")
Else
write_log ("Uyarı Gonderildi")
out_send_message oClient, oMessage, true, usernnr, user_max
End if
Else
write_log ("Limit Dolmak Uzere")
out_send_message oClient, oMessage, true, usernnr, user_max
End If
content = content & arr(0) & " " & usernnr & " " & arr(2) & " W" & nl
Else
content = content & arr(0) & " " & usernnr & " " & arr(2) & nl
End If
Else
content = content & arr(0) & " " & arr(1) & " " & arr(2) & nl
End If
If Mid(arr(2),1,1) <> "@" Then
pos = idt - CLng(arr(0))
dayamounts(pos) = dayamounts(pos) + CLng(arr(1))
End If
Else
write_log ("Basarisiz-2 " & Mid(ln,1,25))
End If
ElseIf Len(ln) > 5 And f.Line > 1 + 1 then
write_log ("Satir Atlandi-1 " & Mid(ln,1,25))
End If
Loop
f.Close
If usernadd Then
content = content & idt & " " & usernnr & " " & usern & nl
End If
Set f = fs.OpenTextFile(outgoingstore, ForWriting, true)
f.Write(content)
f.Close
Else
content = content & idt & " " & usernnr & " " & usern & nl
Set f = fs.OpenTextFile(outgoingstore, ForWriting, true)
f.Write(content)
f.Close
End If
If user_max < usernnr Then
check_limit = false
write_log("ERR")
Else
write_log("OK")
End If
End function
Sub out_send_message(oClient, oMessage, iswarning, nr, max)
Dim txt
Dim tmp
If oclient.username <> "" then
tmp = oclient.username
Else
tmp = oMessage.FromAddress
End If
If iswarning Then
txt = "SAYIN " & tmp & nl & nl
txt = txt & "HESAP GONDERIM LIMITI DOLMAK UZERE." & nl & nl
txt = txt & "GONDERILEN : " & nr & nl
txt = txt & "LIMIT : " & max & nl & nl
Set nMessage = CreateObject("hMailServer.Message")
nMessage.From = msg_from
nMessage.FromAddress = msg_fromaddress
nMessage.AddRecipient tmp, tmp
nMessage.Subject = "UYARI : MAIL GONDERIM LIMITI DOLMAK UZERE"
nMessage.Body = txt
nMessage.Save
Else
txt = "SAYIN " & tmp & nl & nl
txt = txt & "HESAP GONDERIM LIMITI DOLDU." & nl & nl
txt = txt & "GONDERILEN : " & nr & nl
txt = txt & "LIMIT : " & max & nl & nl
Set nMessage = CreateObject("hMailServer.Message")
nMessage.From = msg_from
nMessage.FromAddress = msg_fromaddress
nMessage.AddRecipient tmp, tmp
nMessage.Subject = "UYARI : MAIL GONDERIM DURDURURLDU"
nMessage.Body = txt
nMessage.Save
End If
End Sub
'------------------------------------------------------------------
' General functions of all scripts
'------------------------------------------------------------------
Function get_date
Dim tmp
Dim erg
tmp = Year(Date)
erg = CStr(tmp)
If Month(Date) < 10 Then
tmp = "0" & Month(Date)
Else
tmp = Month(Date)
End If
erg = erg & "-" & tmp
If day(Date) < 10 Then
tmp = "0" & day(Date)
Else
tmp = day(Date)
End If
erg = erg & "-" & tmp
get_date = erg
End Function
Function chk_date
Dim fso
Set fso = CreateObject("scripting.filesystemobject")
Dim old_date
Dim new_date
Dim hedef
new_date = get_date()
If fso.FileExists(date_file) Then
Set fs = fso.OpenTextFile(date_file)
old_date = fs.ReadLine
Set fs = Nothing
If old_date <> new_date Then
Set fs = fso.CreateTextFile(date_file)
fs.WriteLine new_date
Set fs = Nothing
hedef = log_path & "Outgoing_" & get_date() & ".txt"
fso.MoveFile outgoingstore, hedef
End If
else
Set fs = fso.CreateTextFile(date_file)
fs.WriteLine new_date
Set fs = Nothing
end if
Set fso = Nothing
End Function
Sub write_log(txt)
chk_date()
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim fs
Dim f
Set fs = CreateObject("scripting.filesystemobject")
Dim fn
Dim tmp
fn = log_path & "Report_" & get_date & ".log"
Set f = fs.opentextfile(fn, ForAppending, true)
tmp = """" & FormatDateTime(Date + time,0) & """" & Chr(9) & """" & txt & """" & nl
if txt="OK" or txt="ERR" then
tmp = tmp & nl
end if
f.Write(tmp)
f.Close
End Sub
Function nl
nl = Chr(13) & Chr(10)
End function
Function is_local_domain(domain_or_email)
is_local_domain = False
Dim domain
Dim doms
Dim alss
Dim i
Dim j
If InStr(1," " & domain_or_email,"@") > 0 Then
domain = Mid(domain_or_email, InStr(1,domain_or_email,"@") + 1)
Else
domain = domain_or_email
End If
If domain_buffer = "" then
i = 0
Set doms = obapp.Domains
Do While i <= doms.Count - 1
Set dom = doms.Item(i)
domain_buffer = domain_buffer & "#" & dom.Name
j = 0
Set alss = dom.DomainAliases
Do While j <= alss.Count - 1
Set als = alss.item(j)
domain_buffer = domain_buffer & "#" & als.AliasName
j = j + 1
Loop
i = i + 1
Loop
End If
If InStr(1, " " & domain_buffer, domain) > 0 Then
is_local_domain = True
End If
End Function
Function has_client_authenticated(oclient)
has_client_authenticated = false
If oCLient.username <> "" Or InStr(1," " & ipslocalhost, oClient.IPAddress) > 0 Then
has_client_authenticated = true
End if
End Function
' Global variables and settings
'------------------------------------------------------------------
Public obApp
Public domain_buffer
Public Const ipslocalhost = "0.0.0.0" 'separated by #
Public Const user = "Administrator"
Public Const pw = "xXxXx"
Public Const outgoingstore = "E:\hMailServer\Events\Outgoing.txt"
Public Const outgoingexceptions = "E:\hMailServer\Events\Limit.txt"
Public Const date_file = "E:\hMailServer\Events\Limit_Date.txt"
Public Const log_path = "E:\hMailServer\Logs\"
Public Const user_limit = 250
Public Const warning_factor = 0.9
Public Const msg_from = "Deep Design Group <info@ddg.com.tr>"
Public Const msg_fromaddress = "info@ddg.com.tr"
'------------------------------------------------------------------
' Hmailserver Eventhandlers
'------------------------------------------------------------------
Sub OnAcceptMessage(oClient, oMessage)
Result.Value = 0
Set obApp = CreateObject("hMailServer.Application")
Call obApp.Authenticate(user, pw)
If has_client_authenticated(oClient) Then
write_log ("Dogrulandi " & oCLient.username & ", Client " & oClient.IPAddress)
if not check_limit(oClient, oMessage) Then
Result.Message = "Mailserver SMTP outgoing limits."
Result.Value = 2
End if
End if
End Sub
'------------------------------------------------------------------
' SMTP limit outgoing emails of domain and user
'------------------------------------------------------------------
function check_limit(oClient, oMessage)
check_limit = true
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim fs , f
Set fs = CreateObject("scripting.filesystemobject")
Dim idt
Dim content
Dim ln
Dim arr
Dim usern
Dim usernadd
Dim usernnr
Dim user_max
Dim reason
Dim rcptscnt
Dim dayamounts(200)
For i = 0 To 200
dayamounts(i) = 0
Next
Dim pos
Dim minday
minday = 999999
If oclient.username <> "" Then
If instr(1,oclient.username,"@") = 0 Then
usern = oclient.username & "@" & obApp.Settings.DefaultDomain
Else
usern = oclient.username
End If
ElseIf is_local_domain(omessage.fromaddress) then
usern = omessage.fromaddress
Else
usern = "local"
End If
content = "# " & get_date() & " SMTP outgoing storage" & nl & nl
usernadd = true
usernnr = 1
user_max = user_limit
idt = CLng(Date())
rcptscnt = omessage.Recipients.count
write_log("Sayac " & rcptscnt)
write_log(omessage.to)
If fs.FileExists(outgoingexceptions) Then
Set f = fs.OpenTextFile(outgoingexceptions, ForReading)
Do While Not f.AtEndOfStream
ln = f.ReadLine
If ln <> "" And Mid(ln,1,1) <> "#" And Len(ln) > 3 Then
arr = Split(ln,Chr(9))
If UBound(arr) = 1 Then
If arr(0) = usern Then
user_max = CLng(arr(1))
write_log ("Limit " & ln)
End if
Else
write_log ("Limit Basarisiz " & Mid(ln,1,25))
End If
ElseIf Len(ln) > 5 And f.Line > 4 + 1 then
write_log ("Satir Atlandi-1 " & Mid(ln,1,25))
End If
Loop
Else
Set f = fs.OpenTextFile(outgoingexceptions, ForWriting, true)
f.Write("# Outgoing limitation exceptions tab / Chr(9) separated" & nl)
f.Write("# Examples (without # at the beginning)" & nl)
f.Write("# @yourdomain.com 10000" & nl)
f.Write("# address@yourdomain.com 5000" & nl & nl)
f.Close
End If
If fs.FileExists(outgoingstore) Then
Set f = fs.OpenTextFile(outgoingstore, ForReading)
Do While Not f.AtEndOfStream
ln = f.ReadLine
If ln <> "" And Mid(ln,1,1) <> "#" And Len(ln) > 5 Then
arr = Split(ln," ")
If UBound(arr) > 1 Then
If minday > CLng(arr(0)) Then
minday = CLng(arr(0))
End If
End If
If UBound(arr) = 2 Or UBound(arr) = 3 Then
If CLng(arr(0)) = idt And arr(2) = usern Then
usernnr = CLng(arr(1)) + rcptscnt
usernadd = False
write_log ("Eklendi " & ln)
If usernnr > user_max Then
If UBound(arr) = 3 Then
If arr(3) = "X" then
write_log ("Durduruldu")
Else
write_log ("Reddedildi-1")
out_send_message oClient, oMessage, false, usernnr, user_max
End if
Else
write_log ("Reddedildi-2")
out_send_message oClient, oMessage, false, usernnr, user_max
End If
content = content & arr(0) & " " & usernnr & " " & arr(2) & " X" & nl
ElseIf usernnr > user_max * warning_factor then
If UBound(arr) = 3 Then
If arr(3) = "W" then
write_log ("Limit Doldu")
Else
write_log ("Uyarı Gonderildi")
out_send_message oClient, oMessage, true, usernnr, user_max
End if
Else
write_log ("Limit Dolmak Uzere")
out_send_message oClient, oMessage, true, usernnr, user_max
End If
content = content & arr(0) & " " & usernnr & " " & arr(2) & " W" & nl
Else
content = content & arr(0) & " " & usernnr & " " & arr(2) & nl
End If
Else
content = content & arr(0) & " " & arr(1) & " " & arr(2) & nl
End If
If Mid(arr(2),1,1) <> "@" Then
pos = idt - CLng(arr(0))
dayamounts(pos) = dayamounts(pos) + CLng(arr(1))
End If
Else
write_log ("Basarisiz-2 " & Mid(ln,1,25))
End If
ElseIf Len(ln) > 5 And f.Line > 1 + 1 then
write_log ("Satir Atlandi-1 " & Mid(ln,1,25))
End If
Loop
f.Close
If usernadd Then
content = content & idt & " " & usernnr & " " & usern & nl
End If
Set f = fs.OpenTextFile(outgoingstore, ForWriting, true)
f.Write(content)
f.Close
Else
content = content & idt & " " & usernnr & " " & usern & nl
Set f = fs.OpenTextFile(outgoingstore, ForWriting, true)
f.Write(content)
f.Close
End If
If user_max < usernnr Then
check_limit = false
write_log("ERR")
Else
write_log("OK")
End If
End function
Sub out_send_message(oClient, oMessage, iswarning, nr, max)
Dim txt
Dim tmp
If oclient.username <> "" then
tmp = oclient.username
Else
tmp = oMessage.FromAddress
End If
If iswarning Then
txt = "SAYIN " & tmp & nl & nl
txt = txt & "HESAP GONDERIM LIMITI DOLMAK UZERE." & nl & nl
txt = txt & "GONDERILEN : " & nr & nl
txt = txt & "LIMIT : " & max & nl & nl
Set nMessage = CreateObject("hMailServer.Message")
nMessage.From = msg_from
nMessage.FromAddress = msg_fromaddress
nMessage.AddRecipient tmp, tmp
nMessage.Subject = "UYARI : MAIL GONDERIM LIMITI DOLMAK UZERE"
nMessage.Body = txt
nMessage.Save
Else
txt = "SAYIN " & tmp & nl & nl
txt = txt & "HESAP GONDERIM LIMITI DOLDU." & nl & nl
txt = txt & "GONDERILEN : " & nr & nl
txt = txt & "LIMIT : " & max & nl & nl
Set nMessage = CreateObject("hMailServer.Message")
nMessage.From = msg_from
nMessage.FromAddress = msg_fromaddress
nMessage.AddRecipient tmp, tmp
nMessage.Subject = "UYARI : MAIL GONDERIM DURDURURLDU"
nMessage.Body = txt
nMessage.Save
End If
End Sub
'------------------------------------------------------------------
' General functions of all scripts
'------------------------------------------------------------------
Function get_date
Dim tmp
Dim erg
tmp = Year(Date)
erg = CStr(tmp)
If Month(Date) < 10 Then
tmp = "0" & Month(Date)
Else
tmp = Month(Date)
End If
erg = erg & "-" & tmp
If day(Date) < 10 Then
tmp = "0" & day(Date)
Else
tmp = day(Date)
End If
erg = erg & "-" & tmp
get_date = erg
End Function
Function chk_date
Dim fso
Set fso = CreateObject("scripting.filesystemobject")
Dim old_date
Dim new_date
Dim hedef
new_date = get_date()
If fso.FileExists(date_file) Then
Set fs = fso.OpenTextFile(date_file)
old_date = fs.ReadLine
Set fs = Nothing
If old_date <> new_date Then
Set fs = fso.CreateTextFile(date_file)
fs.WriteLine new_date
Set fs = Nothing
hedef = log_path & "Outgoing_" & get_date() & ".txt"
fso.MoveFile outgoingstore, hedef
End If
else
Set fs = fso.CreateTextFile(date_file)
fs.WriteLine new_date
Set fs = Nothing
end if
Set fso = Nothing
End Function
Sub write_log(txt)
chk_date()
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim fs
Dim f
Set fs = CreateObject("scripting.filesystemobject")
Dim fn
Dim tmp
fn = log_path & "Report_" & get_date & ".log"
Set f = fs.opentextfile(fn, ForAppending, true)
tmp = """" & FormatDateTime(Date + time,0) & """" & Chr(9) & """" & txt & """" & nl
if txt="OK" or txt="ERR" then
tmp = tmp & nl
end if
f.Write(tmp)
f.Close
End Sub
Function nl
nl = Chr(13) & Chr(10)
End function
Function is_local_domain(domain_or_email)
is_local_domain = False
Dim domain
Dim doms
Dim alss
Dim i
Dim j
If InStr(1," " & domain_or_email,"@") > 0 Then
domain = Mid(domain_or_email, InStr(1,domain_or_email,"@") + 1)
Else
domain = domain_or_email
End If
If domain_buffer = "" then
i = 0
Set doms = obapp.Domains
Do While i <= doms.Count - 1
Set dom = doms.Item(i)
domain_buffer = domain_buffer & "#" & dom.Name
j = 0
Set alss = dom.DomainAliases
Do While j <= alss.Count - 1
Set als = alss.item(j)
domain_buffer = domain_buffer & "#" & als.AliasName
j = j + 1
Loop
i = i + 1
Loop
End If
If InStr(1, " " & domain_buffer, domain) > 0 Then
is_local_domain = True
End If
End Function
Function has_client_authenticated(oclient)
has_client_authenticated = false
If oCLient.username <> "" Or InStr(1," " & ipslocalhost, oClient.IPAddress) > 0 Then
has_client_authenticated = true
End if
End Function
Last edited by ozhim on 2009-12-22 18:51, edited 1 time in total.
Re: Limit outbound mails by user, domain or server average
What do you mean by
Could you tell me what line in the code you have changed!ozhim wrote:I just want to control users
Re: Limit outbound mails by user, domain or server average
Hello,
thank you for posting this.
I would like to know if you could point out a way to convert the daily limits into absolute limits.
My Best,
Andreas
thank you for posting this.
I would like to know if you could point out a way to convert the daily limits into absolute limits.
My Best,
Andreas
-
- New user
- Posts: 4
- Joined: 2007-09-17 15:48
Re: Limit outbound mails by user, domain or server average
may you explain excactly what and how to use the variable ipslocalhost ?
thanks
thanks
-
- New user
- Posts: 7
- Joined: 2010-04-20 06:11
Re: Limit outbound mails by user, domain or server average
Hi andyp,
The script is really good and useful.
I was just wondering: if the user has reached the limit, when the limit can reset i.e. how the particular user can start sending the e-mails?
Is any manual action required or is it automatic?
Thanks.
The script is really good and useful.
I was just wondering: if the user has reached the limit, when the limit can reset i.e. how the particular user can start sending the e-mails?
Is any manual action required or is it automatic?
Thanks.
Re: Limit outbound mails by user, domain or server average
Hi andyp
Great script but where does the script get the "emailadmin" from?
And i guess you forgot something here
Great script but where does the script get the "emailadmin" from?
And i guess you forgot something here

Code: Select all
If msg_admin_warning then
End If
Re: Limit outbound mails by user, domain or server average
It seems a very good script but I followed the instructions in the .txt file and implemented it but it does not seem to do something.
I can't copy an error message because there is none.
I tested it setting the limit to something small, like 2 messages and nothing.
Maybe it's this: I am using hMail as a mail relay so they arrive from the MTA by the LAN nic and are sended using the WAN nic. I declared only the WAN in the script.
Help plese!
I can't copy an error message because there is none.
I tested it setting the limit to something small, like 2 messages and nothing.
Maybe it's this: I am using hMail as a mail relay so they arrive from the MTA by the LAN nic and are sended using the WAN nic. I declared only the WAN in the script.
Help plese!
-
- Senior user
- Posts: 268
- Joined: 2010-11-19 18:50
Re: Limit outbound mails by user, domain or server average
Thank you for this very very very usefull script. One small question, does it also counts web based sent mails or only pop3 client based sent mails.
Re: Limit outbound mails by user, domain or server average
I'd also like to add my thanks for this one. I was hit by a hacker/spammer the other day and I wish I had this script installed then - it may have prevented 22,000+ spams being sent though my server, and the subsequent blacklist/isp warnings!
Anyway, I had to make a few little changes, mostly undeclared variables (i have option explicit turned on so all variables *have* to be declared).
its all working well so far (tested by sending a load of emails to a safe account.
Thanks loads
Phil
Anyway, I had to make a few little changes, mostly undeclared variables (i have option explicit turned on so all variables *have* to be declared).
its all working well so far (tested by sending a load of emails to a safe account.
Thanks loads

Phil
Re: Limit outbound mails by user, domain or server average
Philg,
Can you post your updated version with the declared variables for others to use?
Can you post your updated version with the declared variables for others to use?
Just 'cause I link to a page and say little else doesn't mean I am not being nice.
https://www.hmailserver.com/documentation
https://www.hmailserver.com/documentation
Re: Limit outbound mails by user, domain or server average
Urm, not easy I'm afraid cos its all mixed in with my other scripts which have been cobbled together from various scripts on here. The changes were mostly in the messages sent - changing the grammar, more than functional - there were 3 undeclared variables, i, k and nMessage which is only important if you turn on "option explicit" which is not on by default, but as a C++ programmer - I hate undeclared variables - IMHO its asking for trouble 
If anyone really wants this, I can try and extract it all back out - but not tonight
Thanks,
Phil

If anyone really wants this, I can try and extract it all back out - but not tonight

Thanks,
Phil
Re: Limit outbound mails by user, domain or server average
No stress, Just thought it may have been easy enough to do.
Don't spend too much work on it.
Don't spend too much work on it.
Just 'cause I link to a page and say little else doesn't mean I am not being nice.
https://www.hmailserver.com/documentation
https://www.hmailserver.com/documentation
Re: Limit outbound mails by user, domain or server average
OK here are my modifications (it was easier than I thought because I had not made so many changes). NOTE That there may be some ommisions in the "generic functions" shared with autowhitelist and other scripts because I did not use those functions from this script.
line 1: Added
Around Line 80: [before For i = 0 To 200] Added...
Around Line 382:[before If oclient.username <> "" then] Added...
NOTE: You don't need to make any changes if you don't use option explicit, but as I mentioned above, I don't like undeclared variables even though vbscript supports it - too it often leads to unexplained errors.
complete list file attached for reference.
line 1: Added
Code: Select all
Option Explicit
Code: Select all
Dim i, k
Code: Select all
Dim nMessage
complete list file attached for reference.
Re: Limit outbound mails by user, domain or server average
very important plugin !
thanks
thanks
Re: Limit outbound mails by user, domain or server average
Just a short note; at line 78 in your script you use a loop
to fill that 200 elements array with "0", now, to speed up
things a little bit, you may use the following code
which will automatically allocate a 200 elements array and
fill it with "0" as needed and will be slightly faster than using
"dim" and the "for...next" loop
- nothing special by the way
but may help a bit
HTH
to fill that 200 elements array with "0", now, to speed up
things a little bit, you may use the following code
Code: Select all
dim dayamounts
dayamounts = Split(Replace(String(400, "0"), "00", "0,") & "0", ",")
fill it with "0" as needed and will be slightly faster than using
"dim" and the "for...next" loop

but may help a bit
HTH
Re: Limit outbound mails by user, domain or server average
Very cool! Thanks!!
And it is very easily adapted to deny certain users from mailing recipients outside their own domain.
And it is very easily adapted to deny certain users from mailing recipients outside their own domain.
Re: Limit outbound mails by user, domain or server average
So I've been testing out these scripts today and I've been getting this error:
Here is what's happening in procmon
Which goes to this line in the script:"ERROR" 1500 "2011-08-31 18:14:57.930" "Script Error: Source: Microsoft VBScript runtime error - Error: 800A0046 - Description: Permission denied - Line: 458 Column: 2 - Code: (null)"
Code: Select all
Public Const logspath = "M:\Program Files\hMailServer\Logs\" 'ends with a backslash
......
Sub write_log(txt)
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim fs
Dim f
If write_log_active then
Set fs = CreateObject("scripting.filesystemobject")
Dim fn
Dim tmp
fn = logspath & "hmailserver_event_" & get_date & ".log"
Set f = fs.opentextfile(fn, ForAppending, true)
tmp = """" & FormatDateTime(Date + time,0) & """" & Chr(9) & """" & txt & """" & nl
f.Write(tmp)
f.Close
End if
End Sub
Here is what's happening in procmon
This only happens when I am load testing the server (the entire server is still in testing), but it happens in as little as 2000 messages sent at once. I think it is leading to many of the emails sent not being counted, so even if the limit is 1000 and 1000 emails are sent, the script only thinks 500 have been sent so far. Has anyone else using this script run into the same issue? I'm looking into it further but I'm a bit out of my depth. ThanksDate & Time: 8/31/2011 6:15:19 PM
Event Class: File System
Operation: CreateFile
Result: SHARING VIOLATION
Path: M:\Program Files\hMailServer\Logs\hmailserver_event_2011-08-31.log
TID: 1504
Duration: 0.0000368
Desired Access: Generic Read/Write
Disposition: OpenIf
Options: Synchronous IO Non-Alert, Non-Directory File
Attributes: N
ShareMode: Read
AllocationSize: 0
Re: Limit outbound mails by user, domain or server average
Hi Masp,
One thing I have learnt about hMailServer scripting in VB, is that its all too easy to get these sorts of problems.
I modified the logging functions to retry and to use a lock file to try and avoid clashes like this. I'm guessing that the server itself is calling multiple scripts in different threads at the same time. This might also account for the not counting all the emails - its far from ideal but on my server, the load is minimal with only 5 or so users, and I still get the occasional problem.
Are you using my modified scripts? I cant remember now if they include all the extra protection I added but I think so. I'm not in front of my server right now so I cant check too easily at the moment.
Thanks,
Phil
One thing I have learnt about hMailServer scripting in VB, is that its all too easy to get these sorts of problems.
I modified the logging functions to retry and to use a lock file to try and avoid clashes like this. I'm guessing that the server itself is calling multiple scripts in different threads at the same time. This might also account for the not counting all the emails - its far from ideal but on my server, the load is minimal with only 5 or so users, and I still get the occasional problem.
Are you using my modified scripts? I cant remember now if they include all the extra protection I added but I think so. I'm not in front of my server right now so I cant check too easily at the moment.
Thanks,
Phil
Re: Limit outbound mails by user, domain or server average
Thanks for responding Phil. I tried your scripts but that section is the same. If you get a chance and can post your updated ones I'd really appreciate it.
Right now I have a web service running that periodically checks the size of the mail queue and sends an alert if it gets huge, but it'd be better to proactive about monitoring the amount of mail people send out.
Right now I have a web service running that periodically checks the size of the mail queue and sends an alert if it gets huge, but it'd be better to proactive about monitoring the amount of mail people send out.
Re: Limit outbound mails by user, domain or server average
I have already posted my updates. I'm fairly sure I've not changed it since the ones you have tried 

Re: Limit outbound mails by user, domain or server average
Thanks I have already corrected the script and will provide it with database support and some other features in the next daysDjGL wrote:Hi andyp
Great script but where does the script get the "emailadmin" from?
And i guess you forgot something here![]()
Code: Select all
If msg_admin_warning then End If
Re: Limit outbound mails by user, domain or server average
I had the same problem and did the same and then I wrote the log into a database, which completly solved it, provide the new script in the next daysphilg wrote:Hi Masp,
One thing I have learnt about hMailServer scripting in VB, is that its all too easy to get these sorts of problems.
I modified the logging functions to retry and to use a lock file to try and avoid clashes like this. I'm guessing that the server itself is calling multiple scripts in different threads at the same time. This might also account for the not counting all the emails - its far from ideal but on my server, the load is minimal with only 5 or so users, and I still get the occasional problem.
Are you using my modified scripts? I cant remember now if they include all the extra protection I added but I think so. I'm not in front of my server right now so I cant check too easily at the moment.
Thanks,
Phil
Re: Limit outbound mails by user, domain or server average
That's why it would be a good idea using the hMS "log" method instead of using custom logfiles, see, the server may handle multiple parallel sessions at once and this also means that it will call multiple times the script so the chances of hitting a filesystem lock contention are higher whenever the server gets loaded; now, if you really need to use a custom logfile, you'd better insert some error checking code into your script and use a "do" loop to retry opening the file a few times (and wait between the various attempts), something like (e.g.)masp wrote:This only happens when I am load testing the server (the entire server is still in testing), but it happens in as little as 2000 messages sent at once. I think it is leading to many of the emails sent not being counted, so even if the limit is 1000 and 1000 emails are sent, the script only thinks 500 have been sent so far. Has anyone else using this script run into the same issue? I'm looking into it further but I'm a bit out of my depth. Thanks
Code: Select all
Sub write_log(txt)
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim fs, f, fn, tmp
Dim bOpened, nErr
On Error Resume Next
If write_log_active then
Set fs = CreateObject("Scripting.FileSystemObject")
fn = logspath & "hmailserver_event_" & get_date & ".log"
bOpened = False
nErr = 0
Do
Err.Clear
Set f = fs.opentextfile(fn, ForAppending, true)
If Err.Number <> 0 Then
nErr = nErr + 1
WScript.Sleep 1000 ' 1 second
Else
bOpened = True
End If
Loop While (bOpened = False) And (nErr < 10)
If bOpened = True Then
tmp = Chr(34) & FormatDateTime(Date + time, 0) & Chr(34) & Chr(9) & Chr(34) & txt & Chr(34) & vbCrLf
f.Write(tmp)
f.Close
End If
End if
End Sub
Re: Limit outbound mails by user, domain or server average
Yes I agree, but while it may be better to use the hMs Log method as described, that means all the log will go to the main hMs log file, which I guess would make debugging the script more difficult hence why the author created his own logs.
Also, these scripts write their own (text) data files so they need protection too, which I'm fairly sure (although not looking at the code right now) was the main change between my version of the script and the original. My VBScript file IO is protected using lock files. If the lock file exists and can not be opened in exclusive write mode, the script waits until it can open it exclusively before continuing. This ensures that only one process/thread can read/write the data file at any time, delaying other instances until the first is finished. Its simplistic but I think it works quite well.
But I guess I didn't bother with the log (which is equally as important of course) and can be done using ObiWan's code snippet which should suffice so long as things are not locked for more than 10 seconds (and the log calls should never take that long!).
Thanks,
Phil
Also, these scripts write their own (text) data files so they need protection too, which I'm fairly sure (although not looking at the code right now) was the main change between my version of the script and the original. My VBScript file IO is protected using lock files. If the lock file exists and can not be opened in exclusive write mode, the script waits until it can open it exclusively before continuing. This ensures that only one process/thread can read/write the data file at any time, delaying other instances until the first is finished. Its simplistic but I think it works quite well.
But I guess I didn't bother with the log (which is equally as important of course) and can be done using ObiWan's code snippet which should suffice so long as things are not locked for more than 10 seconds (and the log calls should never take that long!).
Thanks,
Phil
Re: Limit outbound mails by user, domain or server average
Well... that may be solved easily, just add some kind of "tag" to the entries logged by the script and it will be easy "grepping" the hMS logfile to extract only the script entriesphilg wrote:Yes I agree, but while it may be better to use the hMs Log method as described, that means all the log will go to the main hMs log file, which I guess would make debugging the script more difficult hence why the author created his own logs.

That's another approach but it's risky, see, imagine some process/script keeping the logfile locked for a lot of time or either crashing w/o deleting the lockfile... in such a case the log calls would just "hang" waiting for an unlock; not a good thing imHo !philg wrote:Also, these scripts write their own (text) data files so they need protection too, which I'm fairly sure (although not looking at the code right now) was the main change between my version of the script and the original. My VBScript file IO is protected using lock files. If the lock file exists and can not be opened in exclusive write mode, the script waits until it can open it exclusively before continuing. This ensures that only one process/thread can read/write the data file at any time, delaying other instances until the first is finished. Its simplistic but I think it works quite well.
Right, the loop/delay is just meant to allow the script to wait a bit and retry gaining access to the file and the counter avoids waiting forever; in regular use a write call won't take so much so, after a second the log should return w/o problems or, in the worst case, it will return w/o logging the record but will at least allow the script to continue running and won't cause any "hang"philg wrote:But I guess I didn't bother with the log (which is equally as important of course) and can be done using ObiWan's code snippet which should suffice so long as things are not locked for more than 10 seconds (and the log calls should never take that long!).
Re: Limit outbound mails by user, domain or server average
@philg and ObiWan
I agree to you both, but I have tried it with a lock file and cached the log and writing it at the end of the script, so the file is only opened once, but it didn't fly without 100% errors. So I am currently using a database with odbc, which is a lot better. If you have got an error and you activated the caching, the entire log is gone, thats not good ;-(. For me using the hm log wasn't useful, but it can be easily achieved by modifing one function. I also created taskids to separate the logs for each eventhandler, sometimes the log got mixed, when 2 or more eventhandlers ran at the same time. This is also the advantage of a db, in which you can find you log very fast with sql.
I agree to you both, but I have tried it with a lock file and cached the log and writing it at the end of the script, so the file is only opened once, but it didn't fly without 100% errors. So I am currently using a database with odbc, which is a lot better. If you have got an error and you activated the caching, the entire log is gone, thats not good ;-(. For me using the hm log wasn't useful, but it can be easily achieved by modifing one function. I also created taskids to separate the logs for each eventhandler, sometimes the log got mixed, when 2 or more eventhandlers ran at the same time. This is also the advantage of a db, in which you can find you log very fast with sql.
Re: Limit outbound mails by user, domain or server average
Hi Andy,
Yes I agree that the database sounds like the best solution (and far quicker too). And if you could post the updates to your original scripts, or just a whole new set of scripts and database structure, I'm sure everyone would find it useful
And ObiWan,
Anyway, it has worked well for me for months now (on a fairly low volume server) but I think the database option would be better.
Thanks,
Phil
Yes I agree that the database sounds like the best solution (and far quicker too). And if you could post the updates to your original scripts, or just a whole new set of scripts and database structure, I'm sure everyone would find it useful

And ObiWan,
OK I agree with that, but the description I gave re the locking was a little simplistic. I think if you took a look at my modified scripts that I posted a while back, I think you will find it has protection so it does not hang but at the same times, does its best to ensure the data is not lost - which is not important for log files but is more so for the data files!That's another approach but it's risky, see, imagine some process/script keeping the logfile locked for a lot of time or either crashing w/o deleting the lockfile... in such a case the log calls would just "hang" waiting for an unlock; not a good thing imHo !
Anyway, it has worked well for me for months now (on a fairly low volume server) but I think the database option would be better.
Thanks,
Phil
Re: Limit outbound mails by user, domain or server average
I admit I didn't look at the updated code; yet I think that using the native logging method and adding "tags" to the messages may be a good idea, see, you may then use find/findstr or grep ... or whatever floats your boat to parse the hMS logs and only extract "your" entries while, at the same time, totally avoiding the need for "lock aware" codephilg wrote:OK I agree with that, but the description I gave re the locking was a little simplistic. I think if you took a look at my modified scripts that I posted a while back, I think you will find it has protection so it does not hang but at the same times, does its best to ensure the data is not lost - which is not important for log files but is more so for the data files!
Anyway, it has worked well for me for months now (on a fairly low volume server) but I think the database option would be better.

Code: Select all
Sub LogMsg(sMsg)
objServer.CustomLog sMsg, "c:\foobar\logfile.log"
End Sub

Re: Limit outbound mails by user, domain or server average
Isn't that what EventLog.Write does?
If at first you don't succeed, bomb disposal probably isn't for you! ヅ
Re: Limit outbound mails by user, domain or server average
EventLog.Write would be the right solution, if you like to use the hm log
Re: Limit outbound mails by user, domain or server average
Personally, in this case, I would rather use the custom log and I don't care (for this script) if an occasional log entry gets lost, so long, as ObiWan said, the log funciton does not lock up the server!
For the purpose of this script, the most important thing is to ensure the integrity of the data files. This is why I added the locking (which seems to work for me but using the database to store the data is a much much better idea).
I agree that in general, we should use hMS for logging where possible but this does not help the integrity of any data/text files in use by the scripts. Most of the scripts that extend hMS tend to use text files of some sort to store any data, and any that get updated by the script at runtime potentially have this problem.
AndyP's use of a database via an ODBC (or OLEDB I guess) is a good solution because its much easier to maintain data integrity in that environment than in VBScript, and you can use transactions and database locks etc. to protect the data and the user of the data.
Phil
For the purpose of this script, the most important thing is to ensure the integrity of the data files. This is why I added the locking (which seems to work for me but using the database to store the data is a much much better idea).
I agree that in general, we should use hMS for logging where possible but this does not help the integrity of any data/text files in use by the scripts. Most of the scripts that extend hMS tend to use text files of some sort to store any data, and any that get updated by the script at runtime potentially have this problem.
AndyP's use of a database via an ODBC (or OLEDB I guess) is a good solution because its much easier to maintain data integrity in that environment than in VBScript, and you can use transactions and database locks etc. to protect the data and the user of the data.
Phil