diff --git a/include/api.tickets.php b/include/api.tickets.php
index 60907d56e9edc3bd1694ca633094c4fadc34f40f..1cc51de3f853b1e4dbab206326139c6fd8a0a1cf 100644
--- a/include/api.tickets.php
+++ b/include/api.tickets.php
@@ -122,14 +122,6 @@ class TicketApiController extends ApiController {
         # Create the ticket with the data (attempt to anyway)
         $errors = array();
 
-        if ($topic=Topic::lookup($data['topicId'])) {
-            if ($form=DynamicForm::lookup($topic->ht['form_id'])) {
-                $form = $form->instanciate();
-                if (!$form->isValid())
-                    $errors += $form->errors();
-            }
-        }
-
         $ticket = Ticket::create($data, $errors, $data['source'], $autorespond, $alert);
         # Return errors (?)
         if (count($errors)) {
@@ -145,12 +137,6 @@ class TicketApiController extends ApiController {
             return $this->exerr(500, "Unable to create new ticket: unknown error");
         }
 
-        # Save dynamic form
-        if (isset($form)) {
-            $form->setTicketId($ticket->getId());
-            $form->save();
-        }
-
         return $ticket;
     }
 
diff --git a/include/class.email.php b/include/class.email.php
index 17c03532876a68f01b06e19a448cec389574b5a1..5c0a51c59c1cef1cc7ae0478f83398f2215a0920 100644
--- a/include/class.email.php
+++ b/include/class.email.php
@@ -341,17 +341,12 @@ class Email {
 
         if($errors) return false;
 
-        //Default to default priority and dept..
-        if(!$vars['priority_id'] && $cfg)
-            $vars['priority_id']=$cfg->getDefaultPriorityId();
-        if(!$vars['dept_id'] && $cfg)
-            $vars['dept_id']=$cfg->getDefaultDeptId();
-
         $sql='updated=NOW(),mail_errors=0, mail_lastfetch=NULL'.
              ',email='.db_input($vars['email']).
              ',name='.db_input(Format::striptags($vars['name'])).
              ',dept_id='.db_input($vars['dept_id']).
              ',priority_id='.db_input($vars['priority_id']).
+             ',topic_id='.db_input($vars['topic_id']).
              ',noautoresp='.db_input(isset($vars['noautoresp'])?1:0).
              ',userid='.db_input($vars['userid']).
              ',mail_active='.db_input($vars['mail_active']).
diff --git a/include/class.filter.php b/include/class.filter.php
index 0d9382771e518b2a2e979f2c388e717133cb7f10..4c36541e6e262f097d6e7989d0ee9148d6760496 100644
--- a/include/class.filter.php
+++ b/include/class.filter.php
@@ -123,6 +123,10 @@ class Filter {
         return $this->ht['canned_response_id'];
     }
 
+    function getHelpTopic() {
+        return $this->ht['topic_id'];
+    }
+
     function stopOnMatch() {
         return ($this->ht['stop_on_match']);
     }
@@ -309,6 +313,10 @@ class Filter {
         # Use canned response.
         if ($this->getCannedResponse())
             $ticket['cannedResponseId'] = $this->getCannedResponse();
+
+        # Apply help topic
+        if ($this->getHelpTopic())
+            $ticket['topicId'] = $this->getHelpTopic();
     }
     /* static */ function getSupportedMatches() {
         foreach (static::$match_types as $k=>&$v) {
@@ -498,6 +506,7 @@ class Filter {
             .',dept_id='.db_input($vars['dept_id'])
             .',priority_id='.db_input($vars['priority_id'])
             .',sla_id='.db_input($vars['sla_id'])
+            .',topic_id='.db_input($vars['topic_id'])
             .',match_all_rules='.db_input($vars['match_all_rules'])
             .',stop_onmatch='.db_input(isset($vars['stop_onmatch'])?1:0)
             .',reject_ticket='.db_input(isset($vars['reject_ticket'])?1:0)
diff --git a/include/class.ticket.php b/include/class.ticket.php
index a69109204c85f16a88ab60fa01f2c0b87b1a2d8f..6cde950f52d494aa64ca9ec1324df15fd3fb8be5 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -2230,6 +2230,14 @@ class Ticket {
                     $vars['email'], $filter->getName()));
         }
 
+        if ($vars['topicId'] && ($topic=Topic::lookup($vars['topicId']))) {
+            if ($topic_form = DynamicForm::lookup($topic->ht['form_id'])) {
+                $topic_form = $topic_form->instanciate();
+                if (!$topic_form->getForm()->isValid($field_filter('topic')))
+                    $errors = array_merge($errors, $topic_form->getForm()->errors());
+            }
+        }
+
         $id=0;
         $fields=array();
         $fields['message']  = array('type'=>'*',     'required'=>1, 'error'=>'Message required');
@@ -2293,24 +2301,47 @@ class Ticket {
 
         # Some things will need to be unpacked back into the scope of this
         # function
-        if (isset($vars['autorespond'])) $autorespond=$vars['autorespond'];
+        if (isset($vars['autorespond']))
+            $autorespond = $vars['autorespond'];
 
         # Apply filter-specific priority
         if ($vars['priorityId'])
             $form->setAnswer('priority', null, $vars['priorityId']);
 
+        // If the filter specifies a help topic which has a form associated,
+        // and there was previously either no help topic set or the help
+        // topic did not have a form, there's no need to add it now as (1)
+        // validation is closed, (2) there may be a form already associated
+        // and filled out from the original  help topic, and (3) staff
+        // members can always add more forms now
+
         // OK...just do it.
-        $deptId=$vars['deptId']; //pre-selected Dept if any.
-        $source=ucfirst($vars['source']);
-        $topic=NULL;
+        $deptId = $vars['deptId']; //pre-selected Dept if any.
+        $source = ucfirst($vars['source']);
+
+        // Apply email settings for emailed tickets. Email settings should
+        // trump help topic settins if the email has an associated help
+        // topic
+        if ($vars['emailId'] && ($email=Email::lookup($vars['emailId']))) {
+            $deptId = $deptId ?: $email->getDeptId();
+            $priority = $form->getAnswer('priority');
+            if (!$priority || !$priority->getIdValue())
+                $form->setAnswer('priority', null, $email->getPriorityId());
+            if ($autorespond)
+                $autorespond = $email->autoRespond();
+            $email = null;
+            $source = 'Email';
+        }
+
         // Intenal mapping magic...see if we need to override anything
-        if(isset($vars['topicId']) && ($topic=Topic::lookup($vars['topicId']))) { //Ticket created via web by user/or staff
-            $deptId=$deptId?$deptId:$topic->getDeptId();
+        if (isset($topic)) {
+            $deptId = $deptId ?: $topic->getDeptId();
             $priority = $form->getAnswer('priority');
             if (!$priority || !$priority->getIdValue())
                 $form->setAnswer('priority', null, $topic->getPriorityId());
-            if($autorespond) $autorespond=$topic->autoRespond();
-            $source=$vars['source']?$vars['source']:'Web';
+            if ($autorespond)
+                $autorespond = $topic->autoRespond();
+            $source = $vars['source'] ?: 'Web';
 
             //Auto assignment.
             if (!isset($vars['staffId']) && $topic->getStaffId())
@@ -2319,27 +2350,19 @@ class Ticket {
                 $vars['teamId'] = $topic->getTeamId();
 
             //set default sla.
-            if(isset($vars['slaId']))
-                $vars['slaId'] = $vars['slaId']?$vars['slaId']:$cfg->getDefaultSLAId();
-            elseif($topic && $topic->getSLAId())
+            if (isset($vars['slaId']))
+                $vars['slaId'] = $vars['slaId'] ?: $cfg->getDefaultSLAId();
+            elseif ($topic && $topic->getSLAId())
                 $vars['slaId'] = $topic->getSLAId();
-
-        }elseif($vars['emailId'] && !$vars['deptId'] && ($email=Email::lookup($vars['emailId']))) { //Emailed Tickets
-            $deptId=$email->getDeptId();
-            $priority = $form->getAnswer('priority');
-            if (!$priority || !$priority->getIdValue())
-                $form->setAnswer('priority', null, $email->getPriorityId());
-            if($autorespond) $autorespond=$email->autoRespond();
-            $email=null;
-            $source='Email';
         }
-        //Last minute checks
+
+        // Last minute checks
         $priority = $form->getAnswer('priority');
         if (!$priority || !$priority->getIdValue())
             $form->setAnswer('priority', null, $cfg->getDefaultPriorityId());
-        $deptId=$deptId?$deptId:$cfg->getDefaultDeptId();
-        $topicId=$vars['topicId']?$vars['topicId']:0;
-        $ipaddress=$vars['ip']?$vars['ip']:$_SERVER['REMOTE_ADDR'];
+        $deptId = $deptId ?: $cfg->getDefaultDeptId();
+        $topicId = $vars['topicId'] ?: 0;
+        $ipaddress = $vars['ip'] ?: $_SERVER['REMOTE_ADDR'];
 
         //We are ready son...hold on to the rails.
         $number = Ticket::genRandTicketNumber();
@@ -2375,6 +2398,13 @@ class Ticket {
         // Save the (common) dynamic form
         $form->setTicketId($id);
         $form->save();
+
+        // Save the form data from the help-topic form, if any
+        if ($topic_form) {
+            $topic_form->setTicketId($id);
+            $topic_form->save();
+        }
+
         $ticket->loadDynamicData();
 
         $dept = $ticket->getDept();
diff --git a/include/staff/email.inc.php b/include/staff/email.inc.php
index 193a5347815237a41b2ffbc613cbb0a75b05914f..bd0acace9d75211d73783415115c82f8f2ce7ea3 100644
--- a/include/staff/email.inc.php
+++ b/include/staff/email.inc.php
@@ -63,6 +63,26 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
                 &nbsp;<span class="error">*&nbsp;<?php echo $errors['name']; ?>&nbsp;</span>
             </td>
         </tr>
+        <tr>
+            <td width="180">
+                New Ticket Help Topic
+            </td>
+            <td>
+                <select name="topic_id">
+                    <option value="0" selected="selected">&mdash; Empty &mdash;</option>
+                    <?php
+                    $sql='SELECT topic_id, topic FROM '.TOPIC_TABLE.' T ORDER by topic';
+                    if(($res=db_query($sql)) && db_num_rows($res)){
+                        while(list($id,$name)=db_fetch_row($res)){
+                            $selected=($info['topic_id'] && $id==$info['topic_id'])?'selected="selected"':'';
+                            echo sprintf('<option value="%d" %s>%s</option>',$id,$selected,$name);
+                        }
+                    }
+                    ?>
+                </select>
+                &nbsp;<span class="error"><?php echo $errors['topic_id']; ?></span>
+            </td>
+        </tr>
         <tr>
             <td width="180">
                 New Ticket Priority
diff --git a/include/staff/filter.inc.php b/include/staff/filter.inc.php
index 74e72106859d68501fbc6e490d79a9ddf90a4869..8590c914915618808cc8a4776e0cab3e5800d725 100644
--- a/include/staff/filter.inc.php
+++ b/include/staff/filter.inc.php
@@ -318,6 +318,26 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
                 &nbsp;<span class="error">&nbsp;<?php echo $errors['assign']; ?></span>
             </td>
         </tr>
+        <tr>
+            <td width="180">
+                Help Topic
+            </td>
+            <td>
+                <select name="topic_id">
+                    <option value="0" selected="selected">&mdash; Unchanged &mdash;</option>
+                    <?php
+                    $sql='SELECT topic_id, topic FROM '.TOPIC_TABLE.' T ORDER by topic';
+                    if(($res=db_query($sql)) && db_num_rows($res)){
+                        while(list($id,$name)=db_fetch_row($res)){
+                            $selected=($info['topic_id'] && $id==$info['topic_id'])?'selected="selected"':'';
+                            echo sprintf('<option value="%d" %s>%s</option>',$id,$selected,$name);
+                        }
+                    }
+                    ?>
+                </select>
+                &nbsp;<span class="error"><?php echo $errors['topic_id']; ?></span>
+            </td>
+        </tr>
         <tr>
             <th colspan="2">
                 <em><strong>Admin Notes</strong>: Internal notes.&nbsp;</em>
diff --git a/open.php b/open.php
index acb25fd70a9b94261f80ab1908eff404359d8f45..3d9b90e81f73a9dbf46d8b0c91c2290e649e30d2 100644
--- a/open.php
+++ b/open.php
@@ -29,16 +29,6 @@ if ($_POST) {
             $errors['captcha']='Invalid - try again!';
     }
 
-    $form = false;
-    if ($topic = Topic::lookup($vars['topicId'])) {
-        if ($form = DynamicForm::lookup($topic->ht['form_id'])) {
-            $form = $form->instanciate();
-            // Don't require internal fields (they're not shown)
-            if (!$form->isValid(function($f) { return !$f->get('private'); }))
-                $errors += $form->errors();
-        }
-    }
-
     if (!$errors && $cfg->allowOnlineAttachments() && $_FILES['attachments'])
         $vars['files'] = AttachmentFile::format($_FILES['attachments'], true);
 
@@ -46,11 +36,6 @@ if ($_POST) {
     if(($ticket=Ticket::create($vars, $errors, SOURCE))){
         $msg='Support ticket request created';
         Draft::deleteForNamespace('ticket.client.'.substr(session_id(), -12));
-        // Save the form data from the help-topic form, if any
-        if ($form) {
-            $form->setTicketId($ticket->getId());
-            $form->save();
-        }
         //Logged in...simply view the newly created ticket.
         if($thisclient && $thisclient->isValid()) {
             session_write_close();
diff --git a/scp/tickets.php b/scp/tickets.php
index 2a8c9e6ee4938a4a19ea57812c0a5559499f4255..1655e7027a98ca7af715d3213b4b68c318134692 100644
--- a/scp/tickets.php
+++ b/scp/tickets.php
@@ -485,13 +485,6 @@ if($_POST && !$errors):
                 break;
             case 'open':
                 $ticket=null;
-                if ($topic=Topic::lookup($_POST['topicId'])) {
-                    if ($form = DynamicForm::lookup($topic->ht['form_id'])) {
-                        $form = $form->instanciate();
-                        if (!$form->getForm()->isValid())
-                            $errors = array_merge($errors, $form->getForm()->errors());
-                    }
-                }
                 if(!$thisstaff || !$thisstaff->canCreateTickets()) {
                      $errors['err']='You do not have permission to create tickets. Contact admin for such access';
                 } else {
@@ -501,11 +494,6 @@ if($_POST && !$errors):
                     if(($ticket=Ticket::open($vars, $errors))) {
                         $msg='Ticket created successfully';
                         $_REQUEST['a']=null;
-                        # Save extra dynamic form(s)
-                        if (isset($form)) {
-                            $form->setTicketId($ticket->getId());
-                            $form->save();
-                        }
                         if (!$ticket->checkStaffAccess($thisstaff) || $ticket->isClosed())
                             $ticket=null;
                         Draft::deleteForNamespace('ticket.staff%', $thisstaff->getId());