logo
Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Login


Compatibility issue
quandary
#1 Posted : Sunday, June 06, 2010 2:05:44 AM(UTC)
Rank: Advanced Member

Groups: Member
Joined: 6/6/2010(UTC)
Posts: 59
Points: 183
Location: Switzerland

Ivar, your server is ingenious, I've got it up and running !!!
Works like a charm.


Five things:
#1 Bug in Server.cs (lsMailServer):
m_StartupPath = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) + "\\";
This should be:
m_StartupPath = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + System.IO.Path.DirectorySeparatorChar;


You've moved the server to .NET 3.5.
3.5 is nice, 4.0 is even nicer, but on Linux, we're yet limited to 2.0 and a subset of 3.5.

I've changed it back to 2.0, and the only thing I had to do was implement an own HashSet class.
See below. It's in its own namespace, so it won't distort the .NET 3.5 HashSet class.


Also, can you change lsMailServer to a console app and, in MainX.Main, add:
Code:

private static Server m_pMailServer = null;
...

else if(args[0].ToLower() == "-daemon")
{
m_pMailServer = new Server();
}

It still runs as WindowsForm then, but if supplied -daemon, it runs in console mode.
Still, one would need to add a way to stop the server, then - but right now I can make due with this, because the server runs always anyway.
That would be very nice, because I don't have (or rather don't want) a GUI on my Linux server.


Oh, another one more thing:
Could you add a method to the mailserver-manager with which one can test whether the supplied nameservers actually resolve an URL ?
Or add a more meaningful error message, not exception DNS timeout...
It took me quite long to realize that the problem of not-working mail relay was that the recipient couldn't be resolved, and that I simply needed to add another nameserver...



And another thing:
Quote:

This e-mail is generated by the Server( ************ ) to notify you,
that your message to *******.*******@************.com dated Sat, 05 Jun 2010 21:17:09 +0200 could not be sent at the first attempt.

Recipient *******.*****@********.com' s Server ( <#relay.session_hostname> ) returned the following response: Der Index war außerhalb des Arraybereichs.


Please note Server will attempt to deliver this message for 1 hours.



"Der Index war außerhalb des Arraybereichs" [German], meaning index outside array bounds.
I didn't look into it, but this looks like a bug in the mail relay subroutine.


Here's the HashSet-Class code I talked about:
Code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;


namespace LumiSoft.MailServer.DotNet2_Compatibilty
{

/// <summary>
/// Describe your member here.
/// </summary>
public class HashSet<T> : ICollection<T>, ISerializable, IDeserializationCallback
{
private readonly Dictionary<T, object> dict;

public HashSet()
{
dict = new Dictionary<T, object>();
}

public HashSet(IEnumerable<T> items)
: this()
{
if (items == null)
{
return;
}

foreach (T item in items)
{
Add(item);
}
}

public HashSet<T> NullSet { get { return new HashSet<T>(); } }

#region ICollection<T> Members

public void Add(T item)
{
if (null == item)
{
throw new ArgumentNullException("item");
}

dict[item] = null;
}

/// <summary>
/// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. </exception>
public void Clear()
{
dict.Clear();
}

public bool Contains(T item)
{
return dict.ContainsKey(item);
}

/// <summary>
/// Copies the items of the <see cref="T:System.Collections.Generic.ICollection`1"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
/// </summary>
/// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the items copied from <see cref="T:System.Collections.Generic.ICollection`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param><param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param><exception cref="T:System.ArgumentNullException"><paramref name="array"/> is null.</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="arrayIndex"/> is less than 0.</exception><exception cref="T:System.ArgumentException"><paramref name="array"/> is multidimensional.-or-<paramref name="arrayIndex"/> is equal to or greater than the length of <paramref name="array"/>.-or-The number of items in the source <see cref="T:System.Collections.Generic.ICollection`1"/> is greater than the available space from <paramref name="arrayIndex"/> to the end of the destination <paramref name="array"/>.-or-Type T cannot be cast automatically to the type of the destination <paramref name="array"/>.</exception>
public void CopyTo(T[] array, int arrayIndex)
{
if (array == null) throw new ArgumentNullException("array");
if (arrayIndex < 0 || arrayIndex >= array.Length || arrayIndex >= Count)
{
throw new ArgumentOutOfRangeException("arrayIndex");
}

dict.Keys.CopyTo(array, arrayIndex);
}

/// <summary>
/// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <returns>
/// true if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false. This method also returns false if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </returns>
/// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
public bool Remove(T item)
{
return dict.Remove(item);
}

/// <summary>
/// Gets the number of items contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <returns>
/// The number of items contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </returns>
public int Count
{
get { return dict.Count; }
}

/// <summary>
/// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
/// </summary>
/// <returns>
/// true if the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only; otherwise, false.
/// </returns>
public bool IsReadOnly
{
get
{
return false;
}
}

#endregion

public HashSet<T> Union(HashSet<T> set)
{
HashSet<T> unionSet = new HashSet<T>(this);

if (null == set)
{
return unionSet;
}

foreach (T item in set)
{
if (unionSet.Contains(item))
{
continue;
}

unionSet.Add(item);
}

return unionSet;
}

public HashSet<T> Subtract(HashSet<T> set)
{
HashSet<T> subtractSet = new HashSet<T>(this);

if (null == set)
{
return subtractSet;
}

foreach (T item in set)
{
if (!subtractSet.Contains(item))
{
continue;
}

subtractSet.dict.Remove(item);
}

return subtractSet;
}

public bool IsSubsetOf(HashSet<T> set)
{
HashSet<T> setToCompare = set ?? NullSet;

foreach (T item in this)
{
if (!setToCompare.Contains(item))
{
return false;
}
}

return true;
}

public HashSet<T> Intersection(HashSet<T> set)
{
HashSet<T> intersectionSet = NullSet;

if (null == set)
{
return intersectionSet;
}

foreach (T item in this)
{
if (!set.Contains(item))
{
continue;
}

intersectionSet.Add(item);
}

foreach (T item in set)
{
if (!Contains(item) || intersectionSet.Contains(item))
{
continue;
}

intersectionSet.Add(item);
}

return intersectionSet;
}

public bool IsProperSubsetOf(HashSet<T> set)
{
HashSet<T> setToCompare = set ?? NullSet;

// A is a proper subset of a if the b is a subset of a and a != b
return (IsSubsetOf(setToCompare) && !setToCompare.IsSubsetOf(this));
}

public bool IsSupersetOf(HashSet<T> set)
{
HashSet<T> setToCompare = set ?? NullSet;

foreach (T item in setToCompare)
{
if (!Contains(item))
{
return false;
}
}

return true;
}

public bool IsProperSupersetOf(HashSet<T> set)
{
HashSet<T> setToCompare = set ?? NullSet;

// B is a proper superset of a if b is a superset of a and a != b
return (IsSupersetOf(setToCompare) && !setToCompare.IsSupersetOf(this));
}

public List<T> ToList()
{
return new List<T>(this);
}

#region Implementation of ISerializable

/// <summary>
/// Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo"/> with the data needed to serialize the target object.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> to populate with data. </param><param name="context">The destination (see <see cref="T:System.Runtime.Serialization.StreamingContext"/>) for this serialization. </param><exception cref="T:System.Security.SecurityException">The caller does not have the required permission. </exception>
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null) throw new ArgumentNullException("info");
dict.GetObjectData(info, context);
}

#endregion

#region Implementation of IDeserializationCallback

/// <summary>
/// Runs when the entire object graph has been deserialized.
/// </summary>
/// <param name="sender">The object that initiated the callback. The functionality for this parameter is not currently implemented. </param>
public void OnDeserialization(object sender)
{
dict.OnDeserialization(sender);
}

#endregion

#region Implementation of IEnumerable

/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>1</filterpriority>
public IEnumerator<T> GetEnumerator()
{
return dict.Keys.GetEnumerator();
}

/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>2</filterpriority>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

#endregion
}

} // End Namespace


ivx
#2 Posted : Sunday, June 06, 2010 11:44:09 AM(UTC)
Rank: Administration

Groups: Administration
Joined: 9/15/2006(UTC)
Posts: 2 342
Points: 6 899
Man
Location: Estonia

Was thanked: 104 time(s) in 104 post(s)
Hi,

There are more differences about 2.0 and 3.5, when you use TLS or SSL. SslStream is missing from 2.0.

Also what version do you use ?(version.txt)

I had dns test buttuns, seems i have loosed them from latest, i will re add them.
quandary
#3 Posted : Monday, June 07, 2010 4:22:39 AM(UTC)
Rank: Advanced Member

Groups: Member
Joined: 6/6/2010(UTC)
Posts: 59
Points: 183
Location: Switzerland

Interesting. I see mono supports sslstream, meaning you could compile it with 3.5, I would then simply need to change it back to 2.0 for compilation with mono.
That is, supposed that you don't start using too many 3.5 methods too much ;-))

The version I used:
//----------------------------------------
// Devel Version: http://www.lumisoft.ee/l...loads/MailServer/Devel/
version: 0.95 (xx.xx.2010)




PS:
Quote:
vesrion: 0.681

(and lower), these about 20 entries should be spelled version ;-))


The thing with
m_StartupPath = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) + "\\";
is that it takes the Process FileName's path, which is correct for windows, but on Linux that process is /usr/bin/mono
[PS: this kind of nuisance might also get you on windows, for example if you get the app.config filename in a windows service while onInstall]...
Consequently, on Linux, lsMailServer searches the XML config files in /usr/bin/Settings, instead of the application's path.

m_StartupPath = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + System.IO.Path.DirectorySeparatorChar;
works fine on both Windows + Linux

There seem to be some more things like that that prevent it from running on Linux atm, I'll look into it that week, if I have the time.
Configuring the server from the MailManager form still gets the wrong XML path (/usr/bin/Settings).
I haven't found out yet where that comes from, but I probably will, if I can figure out how all those components interact ;-)).

So far I have it working fine on Windows, but I still prefer good old Linux.
ivx
#4 Posted : Tuesday, June 08, 2010 1:38:34 PM(UTC)
Rank: Administration

Groups: Administration
Joined: 9/15/2006(UTC)
Posts: 2 342
Points: 6 899
Man
Location: Estonia

Was thanked: 104 time(s) in 104 post(s)

I will also look at it if get some time.
Some time ago i runned 0.94 version on suse linux and mono 2.6.

Only problems where that port 25,110,143 are allocated by linux and you need to use different port.
quandary
#5 Posted : Sunday, July 25, 2010 1:37:48 AM(UTC)
Rank: Advanced Member

Groups: Member
Joined: 6/6/2010(UTC)
Posts: 59
Points: 183
Location: Switzerland

ivx wrote:

I will also look at it if get some time.


Well, sorry I had to stall the project for a month because of military service.



ivx wrote:

Some time ago i runned 0.94 version on suse linux and mono 2.6.

Only problems where that port 25,110,143 are allocated by linux and you need to use different port.


These ports aren't allocated/reserved by Linux, they are allocated by default mail-server programs, such as dovecot/sendmail etc.

But yea, that is annoying, Ubuntu delivers dovecot mailserver by default on its server distro.
And I only realized that when I tried to run lsMailServer.
God, that was a good thing, I didn't realize before I had a SMTP server running, but what really strikes me is that they didn't set a send-password by default, damn idiots.


But back to lsMailServer !
Now I finally continued, and found two more bugs:
In the xml_API project in file xml_API.cs you have
Code:

if(!Path.IsPathRooted(m_DataPath))
            {                
                m_DataPath = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) + "\\" + m_DataPath;
            }

if(!Path.IsPathRooted(m_MailStorePath))
            {
                m_MailStorePath = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) + "\\" + m_MailStorePath;
            }


This should be:
System.Reflection.Assembly.GetEntryAssembly().Location
instead of System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName

because it again points to /usr/bin/mono instead of /path/to/executable

So corrected:
m_DataPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + System.IO.Path.DirectorySeparatorChar + m_DataPath;
m_MailStorePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + System.IO.Path.DirectorySeparatorChar + m_MailStorePath;


With this two corrections, it looks like the MailServerManager now works fine on Linux (apart from the fact that the mono team needs to fix its horrible winforms).
quandary
#6 Posted : Sunday, July 25, 2010 2:37:09 AM(UTC)
Rank: Advanced Member

Groups: Member
Joined: 6/6/2010(UTC)
Posts: 59
Points: 183
Location: Switzerland

And another bug: When Settings/Events.xml
is empty, then there is a handled unhandled exception in MailServerManager...
(NULL reference exception)
quandary
#7 Posted : Sunday, July 25, 2010 1:50:25 PM(UTC)
Rank: Advanced Member

Groups: Member
Joined: 6/6/2010(UTC)
Posts: 59
Points: 183
Location: Switzerland

Very well, now it looks like it works, even with the default ports:

tcp 0 0 *:imap2 *:* LISTEN
tcp 0 0 *:smtp *:* LISTEN
tcp 0 0 *:5252 *:* LISTEN
tcp 0 0 *:pop3 *:* LISTEN

I still get a filenotfound exception on startup using trace, and when I stop the server, I get an exception Socket Interrupted <filename unknown>
EventArgs.AcceptCallback <filename unknown>
Is there still one more occurence of incorrect filename/log somewhere ?


Unfortunately, I have an epic ISP failure (the first ever) since the lightenings of that thunderstorm last week, so at the moment, I can't test it, have to wait for SwissCom to fix their equipment.

On Windows, in project lsMailServer.sln add a reference to System.DirectoryServices.Protocols.dll and set LocalCopy to true. Mono seems to lack this assembly.
On Ubuntu, you also need to compile mono 2.6 for letting it run, because in the repos, there is only 2.4, and it won't work with 2.4.


Anybody who needs to compile mono, follow these guides (replacing 2.4 with 2.6):
http://www.centriment.co...m-source-on-ubuntu-810/
http://www.mono-project....allel_Mono_Environments

It works !


One question Ivar: Where do I set Mailstore-Directory in the MailServerManager ?
I didn't find the option, so I had to change it in the XML file directly.


PS: One more thing:
I didn't look at it closely, but it looked to me like you seem to be reading and writing XML manually.

You can avoid all that overhead by directly serializing your XML classes using XML-Serialization:
http://www.devhood.com/t...ils.aspx?tutorial_id=236
ivx
#8 Posted : Monday, July 26, 2010 11:02:51 AM(UTC)
Rank: Administration

Groups: Administration
Joined: 9/15/2006(UTC)
Posts: 2 342
Points: 6 899
Man
Location: Estonia

Was thanked: 104 time(s) in 104 post(s)
Hi,

Funny Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName should work and some time ago i tried with mono 2.4 all worked.
I will try that out, if won't work,, yes these lines can be replaced with both-working ones.
(As i get right, you replaced these in 3 palces only ?)

Only thing with latest may be sqllite, it needs to load right lib for linux.


>I still get a filenotfound exception on startup using trace, and when I stop the server, I get an exception Socket Interrupted <filename unknown>
>EventArgs.AcceptCallback <filename unknown>
>Is there still one more occurence of incorrect filename/log somewhere ?
Do you get this if not default smtp,pop3,imap ports ?


>One question Ivar: Where do I set Mailstore-Directory in the MailServerManager ?
>I didn't find the option, so I had to change it in the XML file directly.
On API propereties ... in UI.

>I didn't look at it closely, but it looked to me like you seem to be reading and writing XML manually.
Nope, standard .NET DataSet with default values.

XML will go off soon, i switch sqllite instead. XML not safe when many writes, whole file needs to be rewritten each time.
Probably i deprecate all other API, will leave possibility to code them but wont maintain other than sqllite by myself.
sqllite has workd ok for imap messages indexing, so seems fast and stable enough.


quandary
#9 Posted : Monday, July 26, 2010 4:17:03 PM(UTC)
Rank: Advanced Member

Groups: Member
Joined: 6/6/2010(UTC)
Posts: 59
Points: 183
Location: Switzerland

ivx wrote:
Hi,

Funny Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName should work and some time ago i tried with mono 2.4 all worked.
I will try that out, if won't work,, yes these lines can be replaced with both-working ones.
(As i get right, you replaced these in 3 palces only ?)

Yes, only at these 3 places.

The thing is, it works when you have binfmt-support installed.
Meaning, when you can start a .NET .executable with ./filename.exe

But when I have to compile mono 2.6, and the distro is still on 2.4, I can't change the binfmt-support, because that might brake other applications.

So in order to start it with mono 2.6 and not system-default mono 2.4, I have to start with mono-2.6 ./filename.exe

Think of it as an interpreter and a compiler.
With binfmt, think of it as running filename.exe standalone/compiled, so the process is filename.exe
Without binfmt, think of it as if running filename.exe interpreted, with the process being the interpreter at /usr/bin/mono-2.6 and not filename.exe.




ivx wrote:

Only thing with latest may be sqllite, it needs to load right lib for linux.

Shouldn't be a problem. SQlite works fine on Linux, never had a problem.
Though SQlite uses some native dll's, so you need to know that you have to replace them with the Linux version.


ivx wrote:

>I didn't look at it closely, but it looked to me like you seem to be reading and writing XML manually.
Nope, standard .NET DataSet with default values.

Yep, makes sense when you work with a bare database, without nhibernate.


ivx wrote:

>I still get a filenotfound exception on startup using trace, and when I stop the server, I get an exception Socket Interrupted <filename unknown>
>EventArgs.AcceptCallback <filename unknown>
>Is there still one more occurence of incorrect filename/log somewhere ?
Do you get this if not default smtp,pop3,imap ports ?

Don't know, will have to try when I get home.


ivx wrote:

>One question Ivar: Where do I set Mailstore-Directory in the MailServerManager ?
>I didn't find the option, so I had to change it in the XML file directly.
On API propereties ... in UI.

API properties ? I don't see any such item anywhere.
But it's not really important.


ivx wrote:

XML will go off soon, i switch sqllite instead. XML not safe when many writes, whole file needs to be rewritten each time.
Probably i deprecate all other API, will leave possibility to code them but wont maintain other than sqllite by myself.
sqllite has workd ok for imap messages indexing, so seems fast and stable enough.

XML writing is never save when you use multithreading, such as in ASP.NET/MailServer, you need to properly lock the file, but that will get you performance problems, if you have many users at the same time. Actually it happened to me that it isn't even save in single-treading, because you can make a web-page (for one user only) with Flash in it (Flash is always asynchronous and uses async http requests), so it can send the next web request to a ashx-handler before the first request has been finished. If both ashx-handlers need to write to the same xml-file --> boooom


If you use SQlite (or at least FirebirdEmbedded), you'll have the same problem if your application is multithreaded, because it will write to the same file at the same time ---> boooom

You need to have the database in a separate, single threaded process, and make tcp connections to it. The database then must queue your request, and process the queue from one and the same thread at all times.



BTW, I'd use Nhibernate, it supports SQlite, MS-SQL, PG-SQL, MySQL, Sybase, Oracle, Firebird, etc.

That way you can keep one code, one API, for all databases.
Then, you only need to take care of views and procedures/functions in the different database yourself, something one can do oneselfs, if one absolutely wants to use lsMailServer with some other database.

One other thing is, if you use Firebird (OpenSource version of InterBase) embedded instead of SQlite (it's not as popular as SQlite), you can use one and the same database/procedure/functions for embedded and non-embedded.
It's a bit hard to get started with Firebird though, since you need something like sql management studio (http://www.sqlmanager.net/products/studio/ibfb), and the thing is while getting a 'free' version isn't difficult, it's not very intuitive. Once you've created the first db file however, it's just as simple, the challenge is creating the first one (one needs to install Firebird server first, connect to it, create the database, then one can take the file and connect to it via embedded-firebird).

The advantage over SQlite is, that you can put the Firebird-file right back into the fully-blown database at any time, without the slightest modification.
quandary
#10 Posted : Wednesday, July 28, 2010 2:03:16 AM(UTC)
Rank: Advanced Member

Groups: Member
Joined: 6/6/2010(UTC)
Posts: 59
Points: 183
Location: Switzerland

Soooo, SwissCom finally fixed its equipment - now it was time for the big test.


Starting with the simplest: The log files for smtp and pop3 etc should be written to the correct path, for example when someone being debugging needs to take a look at them. You forgot to fix the logfile path for Linux/Unix:


In project lsMailServer, in file VirtualServer.cs, in "private void LoadSettings"


After

Code:
if(dr["FetchPOP3_LogPath"].ToString().Trim().Length == 0){
                         m_Fetch_LogPath = m_pOwnerServer.StartupPath + "Logs\\FetchPOP3\\";
                     }




but before
Code:
m_pFetchServer.LogPath = m_Fetch_LogPath;


you need to add
Code:

// Oooops...
m_SMTP_LogPath = API_Utlis.PathFix(m_SMTP_LogPath);
m_POP3_LogPath = API_Utlis.PathFix(m_POP3_LogPath);
m_IMAP_LogPath = API_Utlis.PathFix(m_IMAP_LogPath);
m_Server_LogPath = API_Utlis.PathFix(m_Server_LogPath);
m_Fetch_LogPath = API_Utlis.PathFix(m_Fetch_LogPath);


After modifying those, I got the logs, and there's an authentication error logged (smtp & pop3).
I'll look into it, might be different system default encoding.

It has a good thing though: before this, I didn't know that "log\smtp-20100727.log" is a valid filename on Linux.
quandary
#11 Posted : Wednesday, July 28, 2010 11:30:21 AM(UTC)
Rank: Advanced Member

Groups: Member
Joined: 6/6/2010(UTC)
Posts: 59
Points: 183
Location: Switzerland

Then in lsVirusFiler.cs in function "public FilterResult Filter"
you have:
Code:

string file = Path.GetTempPath() + "\\" + Guid.NewGuid().ToString() + ".eml";
                using(FileStream fs = File.Create(file)){


This should be:
Code:

string file = Path.GetTempPath() + "\\" + Guid.NewGuid().ToString() + ".eml";
file = API_Utlis.PathFix(file);
        using(FileStream fs = File.Create(file)){


or you'll save to /"tmp\GUID.eml"

And in
catch(Exception x) --> No Logging ?
it does not log E-Mails that escape the filter because they cause an exception.
quandary
#12 Posted : Saturday, July 31, 2010 3:58:21 AM(UTC)
Rank: Advanced Member

Groups: Member
Joined: 6/6/2010(UTC)
Posts: 59
Points: 183
Location: Switzerland

Finally solved the problem:

in Net/Auth/AUTH_SASL_ServerMechanism_CramMd5.cs

there is function public override string Continue(string clientResponse)
which has a section
Code:

string hash = Net_Utils.ToHex(HmacMd5(m_Key, result.Password));
if (hash == user_hash[1])
{
m_IsAuthenticated = true;
}



with HmacMd5 :=
Code:

private string HmacMd5(string hashKey, string text)
{
HMACMD5 kMd5 = new HMACMD5(Encoding.Default.GetBytes(text));

return Encoding.Default.GetString(kMd5.ComputeHash(Encoding.ASCII.GetBytes(hashKey)));
}


You should change HmacMd5 to:
Code:

private string HmacMd5(string hashKey, string text)
{
HMACMD5 kMd5 = new HMACMD5(Encoding.Default.GetBytes(text));

string strHash = "";
foreach (byte x in kMd5.ComputeHash(Encoding.ASCII.GetBytes(hashKey)))
{
strHash += x.ToString("x2");

}
return strHash;
}



And in function "function public override string Continue(string clientResponse)"
replace the line
Code:

string hash = Net_Utils.ToHex(HmacMd5(m_Key, result.Password));


With this one:
Code:

string hash = HmacMd5(m_Key, result.Password);





Now it works with POP3 and IMAP, on the default ports, too.
The problem seems to be your encoding change, because the default encoding on windows is 1252, but UTF-8 on Ubuntu Linux, which results in a different string, which therefore has a different hex value. It follows --> the authentication always fails...

That encoding change is, IMHO, completely unnecessary and just plain wrong. No offense, now that the server works, it rulez ;-))

Now that the server runs fine, I'll just have to find out why it keeps throwing an exception when I stop it.
ivx
#13 Posted : Saturday, July 31, 2010 1:14:28 PM(UTC)
Rank: Administration

Groups: Administration
Joined: 9/15/2006(UTC)
Posts: 2 342
Points: 6 899
Man
Location: Estonia

Was thanked: 104 time(s) in 104 post(s)

I removed string conversion part.

Code:

#region method HmacMd5

        /// <summary>
        /// Calculates keyed md5 hash from specifieed text and with specified hash key.
        /// </summary>
        /// <param name="hashKey">MD5 key.</param>
        /// <param name="text">Text to hash.</param>
        /// <returns>Returns MD5 hash.</returns>
        private byte[] HmacMd5(string hashKey,string text)
        {
            HMACMD5 kMd5 = new HMACMD5(Encoding.Default.GetBytes(text));
            
            return kMd5.ComputeHash(Encoding.ASCII.GetBytes(hashKey));
        }

        #endregion


So now it should be ok.

Next week i try to make all path fixes too, then will release new devel version.
quandary
#14 Posted : Sunday, August 08, 2010 8:31:17 PM(UTC)
Rank: Advanced Member

Groups: Member
Joined: 6/6/2010(UTC)
Posts: 59
Points: 183
Location: Switzerland

ivx wrote:

Next week i try to make all path fixes too, then will release new devel version.


Nice.

I was just looking into the database API.
I found you wrote stored procedures for pretty much everything.
Basically as one should.

But the stored procedures are not very complicated and there are no views.
Basically, one should move the SQL queries back to the C# code in the API and use nHibernate.

That way you write the procedures ONCE, and have support for more than MS-SQL and PostGre
(such as MySQL, Oracle, Firebird, Sybase).

So I've started writing an nHibernate API.
I can already create all the tables, and I've read out all the stored procedures interfaces and added them in C#.
Now I still need to replace the stored procedure code with nhibernate calls, which is a bit more work, and full support for all mayor databases is there.

Would you be interested in the code ?
The two existing APIs would remain working.
ivx
#15 Posted : Monday, August 09, 2010 12:02:39 PM(UTC)
Rank: Administration

Groups: Administration
Joined: 9/15/2006(UTC)
Posts: 2 342
Points: 6 899
Man
Location: Estonia

Was thanked: 104 time(s) in 104 post(s)

Yes it would be nice to see your code.
ivx
#16 Posted : Monday, August 09, 2010 1:38:13 PM(UTC)
Rank: Administration

Groups: Administration
Joined: 9/15/2006(UTC)
Posts: 2 342
Points: 6 899
Man
Location: Estonia

Was thanked: 104 time(s) in 104 post(s)
About running as deamon ...

probably this code is better.

Code:

else if(args[0].ToLower() == "-daemon"){
Server server = new Server();

while(true){
System.Threading.Thread.Sleep(1);
}
}
quandary
#17 Posted : Wednesday, August 18, 2010 3:23:15 PM(UTC)
Rank: Advanced Member

Groups: Member
Joined: 6/6/2010(UTC)
Posts: 59
Points: 183
Location: Switzerland

ivx wrote:
About running as deamon ...

probably this code is better.

Code:

else if(args[0].ToLower() == "-daemon"){
Server server = new Server();

while(true){
System.Threading.Thread.Sleep(1);
}
}


;-))

Very true, it shouldn't stop listening right away.

You could also change it to a while not Console.KeyPressed or Console.KeyPressed = '\n' as in XSP.
But that would rather be something for else if(args[0].ToLower() == "-testing")


Being able to set true to false via .NET remoting would also be a good idea.
That way one could stop the server from a management utility, or even the server executable
via if(args[0].ToLower() == "-stopdaemon") arg1 could optionally be the remoting port of the server to stop.


Thinking about it, one could also use the [x]inetd internet superserver to start it on demand, for example when a request enters on port 25.
That might make the wile(true) unnecessary, but it might require program changes.
But I don't really know what is necessary on the server programming side for that it works.
I will ask on ubuntuforums.org .


Edit:
See here:
http://stackoverflow.com...vice-usable-with-xinetd
and here:
http://ubuntuforums.org/showthread.php?t=1555528

Makes xinetd look stupidly simple.
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Powered by YAF 1.9.5.5 | YAF © 2003-2011, Yet Another Forum.NET
This page was generated in 0,278 seconds.