diff --git a/include/class.file.php b/include/class.file.php
index 364e7f14ac570d3cc0c2bb2fa074bb05eef1c29a..da8ad76dc0ed9e9917596829fa7a6450f8176b2d 100644
--- a/include/class.file.php
+++ b/include/class.file.php
@@ -181,7 +181,7 @@ class AttachmentFile {
         $sql='INSERT INTO '.FILE_TABLE.' SET created=NOW() '
             .',type='.db_input($file['type'])
             .',size='.db_input($file['size'])
-            .',name='.db_input($file['name'])
+            .',name='.db_input(Format::file_name($file['name']))
             .',hash='.db_input($file['hash']);
 
         if (!(db_query($sql) && ($id=db_insert_id())))
diff --git a/include/class.format.php b/include/class.format.php
index aaa6667d32c2fce14da2cb9f5e15387ec9608b0c..b510221e02b41a8da8b4bfd27278cfdb9e5d5e9d 100644
--- a/include/class.format.php
+++ b/include/class.format.php
@@ -31,10 +31,7 @@ class Format {
     }
 
     function file_name($filename) {
-
-        $search = array('/ß/','/ä/','/Ä/','/ö/','/Ö/','/ü/','/Ü/','([^[:alnum:]._])');
-        $replace = array('ss','ae','Ae','oe','Oe','ue','Ue','_');
-        return preg_replace($search,$replace,$filename);
+        return preg_replace('/\s+/', '_', $filename);
     }
 
     /* re-arrange $_FILES array for the sane */
diff --git a/include/class.mailfetch.php b/include/class.mailfetch.php
index fce15f537eb6125b5689ebef37879d267e90f850..c567819cbdb27b6e4fe5910865b4a36c0c01faa9 100644
--- a/include/class.mailfetch.php
+++ b/include/class.mailfetch.php
@@ -196,23 +196,25 @@ class MailFetcher {
     //Convert text to desired encoding..defaults to utf8
     function mime_encode($text, $charset=null, $enc='utf-8') { //Thank in part to afterburner  
         
-        if(function_exists('iconv') and $text) {
+        if(function_exists('iconv') and ($charset or function_exists('mb_detect_encoding'))) {
             if($charset)
                 return iconv($charset, $enc.'//IGNORE', $text);
             elseif(function_exists('mb_detect_encoding'))
                 return iconv(mb_detect_encoding($text, $this->encodings), $enc, $text);
+        } elseif(function_exists('iconv_mime_decode')) {
+            return iconv_mime_decode($text, 0, $enc);
         }
 
         return utf8_encode($text);
     }
     
-    //Generic decoder - mirrors imap_utf8
+    //Generic decoder - resuting text is utf8 encoded -> mirrors imap_utf8
     function mime_decode($text) {
         
         $str = '';
         $parts = imap_mime_header_decode($text);
         foreach ($parts as $part)
-            $str.= $part->text;
+            $str.= $this->mime_encode($part->text, ($part->charset=='default'?'ASCII':$part->charset), 'utf-8');
         
         return $str?$str:imap_utf8($text);
     }
@@ -310,15 +312,31 @@ class MailFetcher {
         if($part && !$part->parts) {
             //Check if the part is an attachment.
             $filename = '';
-            if($part->ifdisposition && in_array(strtolower($part->disposition), array('attachment', 'inline')))
+            if($part->ifdisposition && in_array(strtolower($part->disposition), array('attachment', 'inline'))) {
                 $filename = $part->dparameters[0]->value;
-            elseif($part->ifparameters && $part->type == 5) //inline image without disposition.
+                //Some inline attachments have multiple parameters.
+                if(count($part->dparameters)>1) {
+                    foreach($part->dparameters as $dparameter) {
+                        if(strcasecmp($dparameter->attribute, 'FILENAME')) continue;
+                        $filename = $dparameter->value;
+                        break;
+                    }
+                }
+            } elseif($part->ifparameters && $part->type == 5) { //inline image without disposition.
                 $filename = $part->parameters[0]->value;
+                if(count($part->parameters)>1) {
+                    foreach($part->parameters as $parameter) {
+                        if(strcasecmp($parameter->attribute, 'FILENAME')) continue;
+                        $filename = $parameter->value;
+                        break;
+                    }
+                }
+            }
 
             if($filename) {
                 return array(
                         array(
-                            'name'  => $filename,
+                            'name'  => $this->mime_decode($filename),
                             'mime'  => $this->getMimeType($part),
                             'encoding' => $part->encoding,
                             'index' => ($index?$index:1)
diff --git a/include/class.osticket.php b/include/class.osticket.php
index df0766f3d01076377ff9bd16b6ba78aa7ef429e0..bef678239f2d66562e2af1c3d9219e35a4a428fd 100644
--- a/include/class.osticket.php
+++ b/include/class.osticket.php
@@ -136,14 +136,19 @@ class osTicket {
        
         $errors=0;
         foreach($files as &$file) {
-            if(!$this->isFileTypeAllowed($file))
-                $file['error']='Invalid file type for '.$file['name'];
+            //skip no file upload "error" - why PHP calls it an error is beyond me.
+            if($file['error'] && $file['error']==UPLOAD_ERR_NO_FILE) continue;
+
+            if($file['error']) //PHP defined error!
+                $file['error'] = 'File upload error #'.$file['error'];
+            elseif(!$file['tmp_name'] || !is_uploaded_file($file['tmp_name']))
+                $file['error'] = 'Invalid or bad upload POST';
+            elseif(!$this->isFileTypeAllowed($file))
+                $file['error'] = 'Invalid file type for '.$file['name'];
             elseif($file['size']>$this->getConfig()->getMaxFileSize())
-                $file['error']=sprintf('File (%s) is too big. Maximum of %s allowed',
+                $file['error'] = sprintf('File (%s) is too big. Maximum of %s allowed',
                         $file['name'], Format::file_size($this->getConfig()->getMaxFileSize()));
-            elseif(!$file['error'] && !is_uploaded_file($file['tmp_name']))
-                $file['error']='Invalid or bad upload POST';
-
+            
             if($file['error']) $errors++;
         }